-
-
Save yellows8/b1e10caa1d8bb8a46316 to your computer and use it in GitHub Desktop.
Old3DS browser v10.2 -> v10. OSS diff.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/JavaScriptCore/wtf/WKC/FastMallocDebugWKC.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/JavaScriptCore/wtf/WKC/FastMallocDebugWKC.cpp | |
index f839452..59441db 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/JavaScriptCore/wtf/WKC/FastMallocDebugWKC.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/JavaScriptCore/wtf/WKC/FastMallocDebugWKC.cpp | |
@@ -1,4 +1,4 @@ | |
-// Copyright (c) 2010,2011 ACCESS CO., LTD. All rights reserved. | |
+// Copyright (c) 2010,2011,2016 ACCESS CO., LTD. All rights reserved. | |
// | |
// Redistribution and use in source and binary forms, with or without | |
// modification, are permitted provided that the following conditions are | |
@@ -1132,6 +1132,8 @@ static void attachAddressInfo(MemoryInfo& inMemInfo, UsedMemoryInfo& inUsedMemIn | |
{ | |
const int index = findSpanInfo(inMemInfo, inUsedMemInfo, cl); | |
ASSERT(index >= 0 && index < (int)inMemInfo.numSpanArray); | |
+ if (!(index >= 0 && index < (int)inMemInfo.numSpanArray)) | |
+ return; | |
SpanInfo* spanInfo = inMemInfo.spanPtrArray[index]; | |
spanInfo->requestedSize += inUsedMemInfo.requestSize; | |
if (needUsedMemory) { | |
@@ -2324,12 +2326,16 @@ static bool initializeStackTrace() | |
bool ret = false; | |
#if ENABLE(WKC_FASTMALLOC_WIN_STACK_TRACE) | |
- gCurProcess = GetCurrentProcess(); | |
+ static bool initialized = false; | |
+ if (!initialized) { | |
+ initialized = true; | |
+ gCurProcess = GetCurrentProcess(); | |
- SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_OMAP_FIND_NEAREST); | |
+ SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_OMAP_FIND_NEAREST); | |
- if (!SymInitialize(gCurProcess, NULL, TRUE)) { | |
- goto exit_func; | |
+ if (!SymInitialize(gCurProcess, NULL, TRUE)) { | |
+ goto exit_func; | |
+ } | |
} | |
#endif /* ENABLE(WKC_FASTMALLOC_WIN_STACK_TRACE) */ | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebCore/platform/graphics/WKC/PlatformPathWKC.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebCore/platform/graphics/WKC/PlatformPathWKC.cpp | |
index 585294f..08ef693 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebCore/platform/graphics/WKC/PlatformPathWKC.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebCore/platform/graphics/WKC/PlatformPathWKC.cpp | |
@@ -258,6 +258,8 @@ static void addArcPoints(PathPolygon& poly, const PlatformPathElement::ArcTo& da | |
double curAngle = startPoint - data.m_center; | |
double endAngle = data.m_end - data.m_center; | |
double angleStep = 2. / std::max(data.m_radius.m_x, data.m_radius.m_y); | |
+ if (fabs(angleStep) < 1E-10) | |
+ return; | |
if (data.m_clockwise) { | |
if (endAngle <= curAngle || startPoint == data.m_end) | |
endAngle += 2 * piDouble; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebCore/platform/network/WKC/ResourceHandleManager.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebCore/platform/network/WKC/ResourceHandleManager.cpp | |
index 754e2c8..dc3ba1e 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebCore/platform/network/WKC/ResourceHandleManager.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebCore/platform/network/WKC/ResourceHandleManager.cpp | |
@@ -12,7 +12,7 @@ | |
* Copyright (C) 2009 Appcelerator Inc. | |
* Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org> | |
* All rights reserved. | |
- * Copyright (c) 2010-2013 ACCESS CO., LTD. All rights reserved. | |
+ * Copyright (c) 2010-2013, 2016 ACCESS CO., LTD. All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
@@ -1471,9 +1471,11 @@ static void parseDataUrl(ResourceHandle* job) | |
{ | |
FUNCTIONPRINTF(("<rhm>parseDataUrl(%p)", job)); | |
- ResourceHandleClient* client = job->client(); | |
- ASSERT(client); | |
- if (!client) | |
+ if (!job || job->getInternal()->m_cancelled) | |
+ return; | |
+ | |
+ ASSERT(job->client()); | |
+ if (!job->client()) | |
return; | |
String url = job->request().url().string(); | |
@@ -1481,7 +1483,7 @@ static void parseDataUrl(ResourceHandle* job) | |
int index = url.find(','); | |
if (index == -1) { | |
- client->cannotShowURL(job); | |
+ job->client()->cannotShowURL(job); | |
return; | |
} | |
@@ -1506,18 +1508,21 @@ static void parseDataUrl(ResourceHandle* job) | |
if (base64) { | |
data = decodeURLEscapeSequences(data); | |
response.setTextEncodingName(charset); | |
- client->didReceiveResponse(job, response); | |
if (job->getInternal()->m_cancelled) | |
return; | |
- client = job->client(); | |
+ if (job->client()) | |
+ job->client()->didReceiveResponse(job, response); | |
+ | |
+ if (job->getInternal()->m_cancelled) | |
+ return; | |
// WebCore's decoder fails on Acid3 test 97 (whitespace). | |
Vector<char> out; | |
- if (client && base64Decode(data.latin1().data(), data.latin1().length(), out) && out.size() > 0) { | |
- client->willReceiveData(job, out.size()); | |
+ if (job->client() && base64Decode(data.latin1().data(), data.latin1().length(), out) && out.size() > 0) { | |
+ job->client()->willReceiveData(job, out.size()); | |
if (job->getInternal()->m_cancelled) | |
return; | |
- client->didReceiveData(job, out.data(), out.size(), 0); | |
+ job->client()->didReceiveData(job, out.data(), out.size(), 0); | |
if (job->getInternal()->m_cancelled) | |
return; | |
} | |
@@ -1525,23 +1530,24 @@ static void parseDataUrl(ResourceHandle* job) | |
// We have to convert to UTF-16 early due to limitations in KURL | |
data = decodeURLEscapeSequences(data, TextEncoding(charset)); | |
response.setTextEncodingName("UTF-16"); | |
- client->didReceiveResponse(job, response); | |
+ if (job->client()) | |
+ job->client()->didReceiveResponse(job, response); | |
if (job->getInternal()->m_cancelled) | |
return; | |
- client = job->client(); | |
- if (client && data.length() > 0) { | |
- client->willReceiveData(job, data.length() * sizeof(UChar)); | |
+ if (job->client() && data.length() > 0) { | |
+ job->client()->willReceiveData(job, data.length() * sizeof(UChar)); | |
if (job->getInternal()->m_cancelled) | |
return; | |
- client->didReceiveData(job, reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0); | |
+ if (job->client()) | |
+ job->client()->didReceiveData(job, reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0); | |
if (job->getInternal()->m_cancelled) | |
return; | |
} | |
} | |
- if (client) | |
- client->didFinishLoading(job); | |
+ if (job->client()) | |
+ job->client()->didFinishLoading(job); | |
} | |
void ResourceHandleManager::dispatchSynchronousJob(ResourceHandle* job) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebCore/platform/network/WKC/ResourceHandleManagerSSL.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebCore/platform/network/WKC/ResourceHandleManagerSSL.cpp | |
index 0c9970f..6e2e7ba 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebCore/platform/network/WKC/ResourceHandleManagerSSL.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebCore/platform/network/WKC/ResourceHandleManagerSSL.cpp | |
@@ -1,5 +1,5 @@ | |
/* | |
- * Copyright (c) 2010,2011 ACCESS CO., LTD. All rights reserved. | |
+ * Copyright (c) 2010,2011,2016 ACCESS CO., LTD. All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
@@ -504,7 +504,7 @@ void ResourceHandleManagerSSL::initializeHandleSSL(ResourceHandle* job) | |
curl_easy_setopt(d->m_handle, CURLOPT_SSL_STATE_FUNCTION, ssl_state_callback); | |
curl_easy_setopt(d->m_handle, CURLOPT_SSL_STATE_DATA, job); | |
- curl_easy_setopt(d->m_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); | |
+ curl_easy_setopt(d->m_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1|CURL_SSLVERSION_TLSv1_1|CURL_SSLVERSION_TLSv1_2); | |
curl_easy_setopt(d->m_handle, CURLOPT_CERTINFO, 1L); | |
if (allowsServerHost(SSLhostAndPort(kurl))) { | |
@@ -516,6 +516,8 @@ void ResourceHandleManagerSSL::initializeHandleSSL(ResourceHandle* job) | |
curl_easy_setopt(d->m_handle, CURLOPT_SSL_VERIFYPEER, 1); | |
} | |
+ curl_easy_setopt(d->m_handle, CURLOPT_SSL_CIPHER_LIST, "ALL:!aNULL:!eNULL:!SSLv2:!RC2:!RC4:!DES:!EXPORT56:!ADH:+HIGH:+MEDIUM:!LOW"); | |
+ | |
d->m_SSLVerifyPeerResult = 0; | |
d->m_SSLVerifyHostResult = 0; | |
d->m_certChain = 0; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebCore/platform/text/WKC/TextCodecWKC.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebCore/platform/text/WKC/TextCodecWKC.cpp | |
index c252799..2ffb433 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebCore/platform/text/WKC/TextCodecWKC.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebCore/platform/text/WKC/TextCodecWKC.cpp | |
@@ -3,7 +3,7 @@ | |
* Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> | |
* Copyright (C) 2008 Jurg Billeter <j@bitron.ch> | |
* Copyright (C) 2009 Dominik Rottsches <dominik.roettsches@access-company.com> | |
- * Copyright (c) 2010,2011 ACCESS CO., LTD. All rights reserved. | |
+ * Copyright (c) 2010,2011,2016 ACCESS CO., LTD. All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
@@ -447,16 +447,30 @@ TextCodecWKC::decode(const char* str, size_t length, bool flush, bool stopOnErro | |
} | |
CString | |
-TextCodecWKC::encode(const UChar* str, size_t length, UnencodableHandling) | |
+TextCodecWKC::encode(const UChar* str, size_t length, UnencodableHandling handling) | |
{ | |
int len, len2; | |
char* buf = NULL; | |
int remains = 0; | |
CString ret; | |
+ int fallback = WKC_I18N_ENCODEERRORFALLBACK_NONE; | |
if (!str || !length) { | |
goto error_end; | |
} | |
+ switch (handling) { | |
+ case QuestionMarksForUnencodables: | |
+ fallback = WKC_I18N_ENCODEERRORFALLBACK_QUESTION; | |
+ break; | |
+ case EntitiesForUnencodables: | |
+ fallback = WKC_I18N_ENCODEERRORFALLBACK_ESCAPE_XML_DECIMAL; | |
+ break; | |
+ case URLEncodedEntitiesForUnencodables: | |
+ fallback = WKC_I18N_ENCODEERRORFALLBACK_ESCAPE_URLENCODE; | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
// should we consider dividing between surrogate pair ? | |
// 100331 ACCESS Co.,Ltd. | |
@@ -467,14 +481,14 @@ TextCodecWKC::encode(const UChar* str, size_t length, UnencodableHandling) | |
goto error_end; | |
} | |
} | |
- len = wkcI18NEncodePeer(m_encoder, str, length, NULL, NULL, &remains); | |
+ len = wkcI18NEncodePeer(m_encoder, str, length, NULL, NULL, &remains, fallback); | |
if (len<=0) { | |
goto error_end; | |
} | |
len += wkcI18NFlushEncodeStatePeer(m_encoder, false, NULL, NULL); | |
ret = CString::newUninitialized(len, buf); | |
- len2 = wkcI18NEncodePeer(m_encoder, str, length, buf, len, &remains); | |
+ len2 = wkcI18NEncodePeer(m_encoder, str, length, buf, len, &remains, fallback); | |
wkcI18NFlushEncodeStatePeer(m_encoder, false, buf + len2, len - len2); | |
return ret; | |
@@ -482,32 +496,32 @@ TextCodecWKC::encode(const UChar* str, size_t length, UnencodableHandling) | |
error_end: | |
return CString(""); | |
} | |
- | |
-// returned value: 0 or more if succeeded, -1 if failed. | |
-int | |
-TextCodecWKC::getDecodedTextLength(const char* str, size_t length) | |
-{ | |
- int ulen = 0; | |
- | |
- if (!m_decoder) { | |
- m_decoder = wkcI18NBeginDecodePeer(m_codecId); | |
- if (!m_decoder) { | |
- return -1; | |
- } | |
- } | |
- | |
- if (!str || !length) { | |
- return 0; | |
- } | |
- | |
- wkcI18NSaveDecodeStatePeer(m_decoder); | |
- ulen = decode(str, length, 0, 0); | |
- wkcI18NRestoreDecodeStatePeer(m_decoder); | |
- if (ulen < 0) { | |
- return -1; | |
- } | |
- | |
- return ulen; | |
-} | |
+ | |
+// returned value: 0 or more if succeeded, -1 if failed. | |
+int | |
+TextCodecWKC::getDecodedTextLength(const char* str, size_t length) | |
+{ | |
+ int ulen = 0; | |
+ | |
+ if (!m_decoder) { | |
+ m_decoder = wkcI18NBeginDecodePeer(m_codecId); | |
+ if (!m_decoder) { | |
+ return -1; | |
+ } | |
+ } | |
+ | |
+ if (!str || !length) { | |
+ return 0; | |
+ } | |
+ | |
+ wkcI18NSaveDecodeStatePeer(m_decoder); | |
+ ulen = decode(str, length, 0, 0); | |
+ wkcI18NRestoreDecodeStatePeer(m_decoder); | |
+ if (ulen < 0) { | |
+ return -1; | |
+ } | |
+ | |
+ return ulen; | |
+} | |
} // namespace WebCore | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebKit/WKC/WebCoreSupport/FrameLoaderClientWKC.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebKit/WKC/WebCoreSupport/FrameLoaderClientWKC.cpp | |
index 11f0260..a6efe85 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebKit/WKC/WebCoreSupport/FrameLoaderClientWKC.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebKit/WKC/WebCoreSupport/FrameLoaderClientWKC.cpp | |
@@ -614,8 +614,9 @@ FrameLoaderClientWKC::createFrame(const WebCore::KURL& url, const WebCore::Strin | |
if (!child) return 0; | |
RefPtr<WebCore::Frame> childframe = adoptRef(child->privateFrame()->core()); | |
- frame->tree()->appendChild(childframe); | |
+ | |
childframe->tree()->setName(name); | |
+ frame->tree()->appendChild(childframe); | |
childframe->init(); | |
if (!childframe->page()) { | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebKit/WKC/webkit/WKCVersion.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebKit/WKC/webkit/WKCVersion.h | |
index fc153c4..09d458a 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebKit/WKC/webkit/WKCVersion.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebKit/WKC/webkit/WKCVersion.h | |
@@ -1,7 +1,7 @@ | |
/* | |
* WKCVersion.h | |
* | |
- * Copyright (c) 2013-2015 ACCESS CO., LTD. All rights reserved. | |
+ * Copyright (c) 2013-2016 ACCESS CO., LTD. All rights reserved. | |
* | |
* This library is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU Library General Public | |
@@ -29,7 +29,7 @@ | |
#define WKC_VERSION_CHECK(major, minor, micro) \ | |
(((major)*10000) + ((minor)*100) + (micro)) >= ((WKC_VERSION_MAJOR*10000) + (WKC_VERSION_MINOR*100) + (WKC_VERSION_MICRO)) | |
-#define WKC_CUSTOMER_RELEASE_VERSION "1.8.17" | |
+#define WKC_CUSTOMER_RELEASE_VERSION "1.8.18" | |
#define WKC_WEBKIT_VERSION "532.7" | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebKit/WKC/webkit/WKCWebFrame.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebKit/WKC/webkit/WKCWebFrame.cpp | |
index a1a9d3a..948d983 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebKit/WKC/webkit/WKCWebFrame.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebKit/WKC/webkit/WKCWebFrame.cpp | |
@@ -216,7 +216,6 @@ WKCWebFrame::construct(WKCWebViewPrivate* view, WKCClientBuilders& builders, WKC | |
} | |
m_private = WKCWebFramePrivate::create(this, view, builders, owner); | |
if (!m_private) return false; | |
- m_private->core()->init(); | |
return true; | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebKit/WKC/webkit/WKCWebView.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebKit/WKC/webkit/WKCWebView.cpp | |
index 47ebea4..a1bcb40 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/WKC/WebKit/WKC/webkit/WKCWebView.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/WKC/WebKit/WKC/webkit/WKCWebView.cpp | |
@@ -11,7 +11,7 @@ | |
Copyright (C) 2009 Igalia S.L. | |
Copyright (C) 2009 Movial Creative Technologies Inc. | |
Copyright (C) 2009 Bobby Powers | |
- Copyright (c) 2010-2013 ACCESS CO., LTD. All rights reserved. | |
+ Copyright (c) 2010-2015 ACCESS CO., LTD. All rights reserved. | |
This library is free software; you can redistribute it and/or | |
modify it under the terms of the GNU Lesser General Public | |
@@ -160,6 +160,7 @@ | |
#include "html/HTMLOptGroupElement.h" | |
#include "html/HTMLOptionElement.h" | |
#include "html/HTMLParser.h" | |
+#include "html/HTMLTokenizer.h" | |
#include "html/HTMLSelectElement.h" | |
#include "html/HTMLTableElement.h" | |
#include "html/HTMLTextAreaElement.h" | |
@@ -279,6 +280,7 @@ extern bool initializeSharedTimer(); | |
extern void finalizeSharedTimer(); | |
extern void RenderThemeWKC_resetVariables(); | |
+extern void RenderSlider_resetVariables(); | |
extern void CookieJar_resetVariables(); | |
extern void JSImageDataCustom_deleteSharedInstance(); | |
extern void JSImageDataCustom_resetVariables(); | |
@@ -467,6 +469,7 @@ WKCWebViewPrivate::construct() | |
m_mainFrame = WKC::WKCWebFrame::create(this, m_clientBuilders); | |
if (!m_mainFrame) goto error_end; | |
+ m_mainFrame->privateFrame()->core()->init(); | |
m_dropdownlist = WKC::DropDownListClientWKC::create(this); | |
if (!m_dropdownlist) goto error_end; | |
@@ -3594,6 +3597,7 @@ WKCWebKitResetVariables() | |
WebCore::HTMLOptGroupElement::resetVariables(); | |
WebCore::HTMLOptionElement::resetVariables(); | |
WebCore::HTMLParser::resetVariables(); | |
+ WebCore::HTMLTokenizer::resetVariables(); | |
WebCore::HTMLSelectElement::resetVariables(); | |
WebCore::HTMLTableElement::resetVariables(); | |
WebCore::HTMLTextAreaElement::resetVariables(); | |
@@ -3614,6 +3618,7 @@ WKCWebKitResetVariables() | |
WebCore::Pasteboard::resetVariables(); | |
WebCore::RenderThemeWKC_resetVariables(); | |
+ WebCore::RenderSlider_resetVariables(); | |
WebCore::ScrollbarTheme::resetVariables(); | |
WebCore::HTMLElementFactory::resetVariables(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/ChangeLog b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/ChangeLog | |
index bf0c440..69ad491 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/ChangeLog | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/ChangeLog | |
@@ -1,3 +1,144 @@ | |
+2013-08-16 Filip Pizlo <fpizlo@apple.com> | |
+ | |
+ Object properties added using dot syntax (o.f = ...) from code that isn't in eval should be less likely to cause an object to become a dictionary | |
+ https://bugs.webkit.org/show_bug.cgi?id=119897 | |
+ | |
+ Reviewed by Oliver Hunt. | |
+ | |
+ 6-10x speed-up on microbenchmarks that create large static objects. 40-65% speed-up | |
+ on Octane/gbemu. 3% overall speed-up on Octane. No slow-downs anywhere; our ability | |
+ to turn objects into dictionaries when you're storing using bracket syntax or using | |
+ eval is still in place. | |
+ | |
+ * bytecode/CodeBlock.h: | |
+ (JSC::CodeBlock::putByIdContext): | |
+ * dfg/DFGOperations.cpp: | |
+ * jit/JITStubs.cpp: | |
+ (JSC::DEFINE_STUB_FUNCTION): | |
+ * llint/LLIntSlowPaths.cpp: | |
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL): | |
+ * runtime/JSObject.h: | |
+ (JSC::JSObject::putDirectInternal): | |
+ * runtime/PutPropertySlot.h: | |
+ (JSC::PutPropertySlot::PutPropertySlot): | |
+ (JSC::PutPropertySlot::context): | |
+ * runtime/Structure.cpp: | |
+ (JSC::Structure::addPropertyTransition): | |
+ * runtime/Structure.h: | |
+ | |
+2012-11-26 Daniel Bates <dbates@webkit.org> | |
+ | |
+ JavaScript fails to handle String.replace() with large replacement string | |
+ https://bugs.webkit.org/show_bug.cgi?id=102956 | |
+ <rdar://problem/12738012> | |
+ | |
+ Reviewed by Oliver Hunt. | |
+ | |
+ Fix an issue where we didn't check for overflow when computing the length | |
+ of the result of String.replace() with a large replacement string. | |
+ | |
+ * runtime/StringPrototype.cpp: | |
+ (JSC::jsSpliceSubstringsWithSeparators): | |
+ | |
+2011-10-18 Gavin Barraclough <barraclough@apple.com> | |
+ | |
+ Array.prototype methods missing exception checks | |
+ https://bugs.webkit.org/show_bug.cgi?id=70360 | |
+ | |
+ Reviewed by Geoff Garen. | |
+ | |
+ Missing exception checks after calls to the static getProperty helper, | |
+ these may result in the wrong exception being thrown (or an ASSERT being hit, | |
+ as is currently the case running test-262). | |
+ | |
+ No performance impact. | |
+ | |
+ * runtime/ArrayPrototype.cpp: | |
+ (JSC::arrayProtoFuncConcat): | |
+ (JSC::arrayProtoFuncReverse): | |
+ (JSC::arrayProtoFuncShift): | |
+ (JSC::arrayProtoFuncSlice): | |
+ (JSC::arrayProtoFuncSplice): | |
+ (JSC::arrayProtoFuncUnShift): | |
+ (JSC::arrayProtoFuncReduce): | |
+ (JSC::arrayProtoFuncReduceRight): | |
+ (JSC::arrayProtoFuncIndexOf): | |
+ (JSC::arrayProtoFuncLastIndexOf): | |
+ | |
+2011-05-31 Yong Li <yoli@rim.com> | |
+ | |
+ Reviewed by Eric Seidel. | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=54807 | |
+ We have been assuming plain bitfields (like "int a : 31") are always signed integers. | |
+ However some compilers can treat them as unsigned. For example, RVCT 4.0 states plain | |
+ bitfields (declared without either signed or unsigned qualifiers) are treats as unsigned. | |
+ http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0348c/Babjddhe.html | |
+ Although we can use "--signed-bitfields" flag to make RVCT 4.0 behave as most other compilers, | |
+ always using "signed"/"unsigned" qualifier to declare integral type bitfields is still a good | |
+ rule we should have in order to make our code independent from compilers and compiler flags. | |
+ | |
+ No new test added because this change is not known to fix any issue. | |
+ | |
+ * bytecode/StructureStubInfo.h: | |
+ | |
+2011-04-12 Gavin Barraclough <barraclough@apple.com> | |
+ | |
+ Reviewed by Oliver Hunt. | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=58395 | |
+ Exceptions thrown from property getters called from Array prototype functions can be missed | |
+ | |
+ This is caught by an ASSERT in the top of Interpreter::executeCall. | |
+ Check for exceptions after accessing properties that could be getters. | |
+ | |
+ * runtime/ArrayPrototype.cpp: | |
+ (JSC::arrayProtoFuncSort): | |
+ (JSC::arrayProtoFuncFilter): | |
+ (JSC::arrayProtoFuncMap): | |
+ (JSC::arrayProtoFuncEvery): | |
+ (JSC::arrayProtoFuncForEach): | |
+ (JSC::arrayProtoFuncSome): | |
+ (JSC::arrayProtoFuncReduce): | |
+ (JSC::arrayProtoFuncReduceRight): | |
+ - Add exception checks. | |
+ | |
+2011-01-18 Oliver Hunt <oliver@apple.com> | |
+ | |
+ Reviewed by Antti Koivisto. | |
+ | |
+ [jsfunfuzz] Assertion in codegen for array of NaN constants | |
+ https://bugs.webkit.org/show_bug.cgi?id=52643 | |
+ | |
+ Don't cache NaN literals in the code generator, as NaN doesn't compare | |
+ as equal to itself it causes problems when rehashing the number cache. | |
+ | |
+ * bytecompiler/BytecodeGenerator.cpp: | |
+ (JSC::BytecodeGenerator::emitLoad): | |
+ | |
+2010-09-29 Sam Weinig <sam@webkit.org> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ Add additional checks to StringBuffer. | |
+ <rdar://problem/7756381> | |
+ | |
+ * wtf/text/StringBuffer.h: | |
+ (WTF::StringBuffer::StringBuffer): | |
+ (WTF::StringBuffer::resize): | |
+ | |
+2010-01-13 Alexey Proskuryakov <ap@apple.com> | |
+ | |
+ Reviewed by NOBODY (OOPS!). | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=33641 | |
+ Assertion failure in Lexer.cpp if input stream ends while in string escape | |
+ | |
+ Test: fast/js/end-in-string-escape.html | |
+ | |
+ * parser/Lexer.cpp: (JSC::Lexer::lex): Bail out quickly on end of stream, not giving the | |
+ assertion a chance to fire. | |
+ | |
2010-01-08 Norbert Leser <norbert.leser@nokia.com> | |
Reviewed by Darin Adler. | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/bytecode/CodeBlock.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/bytecode/CodeBlock.h | |
index eb874cc..35275a7 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/bytecode/CodeBlock.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/bytecode/CodeBlock.h | |
@@ -36,6 +36,7 @@ | |
#include "JSGlobalObject.h" | |
#include "JumpTable.h" | |
#include "Nodes.h" | |
+#include "PutPropertySlot.h" | |
#include "PtrAndFlags.h" | |
#include "RegExp.h" | |
#include "UString.h" | |
@@ -376,6 +377,12 @@ namespace JSC { | |
bool usesArguments() const { return m_usesArguments; } | |
CodeType codeType() const { return m_codeType; } | |
+ PutPropertySlot::Context putByIdContext() const | |
+ { | |
+ if (codeType() == EvalCode) | |
+ return PutPropertySlot::PutByIdEval; | |
+ return PutPropertySlot::PutById; | |
+ } | |
SourceProvider* source() const { return m_source.get(); } | |
unsigned sourceOffset() const { return m_sourceOffset; } | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/bytecode/StructureStubInfo.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/bytecode/StructureStubInfo.h | |
index 8e2c489..1d49245 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/bytecode/StructureStubInfo.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/bytecode/StructureStubInfo.h | |
@@ -140,8 +140,8 @@ namespace JSC { | |
seen = true; | |
} | |
- int accessType : 31; | |
- int seen : 1; | |
+ signed accessType : 31; | |
+ unsigned seen : 1; | |
union { | |
struct { | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp | |
index 4cf543c..a050f22 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp | |
@@ -985,8 +985,9 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b) | |
RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number) | |
{ | |
// FIXME: Our hash tables won't hold infinity, so we make a new JSNumberCell each time. | |
- // Later we can do the extra work to handle that like the other cases. | |
- if (number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number)) | |
+ // Later we can do the extra work to handle that like the other cases. They also don't | |
+ // work correctly with NaN as a key. | |
+ if (isnan(number) || number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number)) | |
return emitLoad(dst, jsNumber(globalData(), number)); | |
JSValue& valueInMap = m_numberMap.add(number, JSValue()).first->second; | |
if (!valueInMap) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/interpreter/Interpreter.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/interpreter/Interpreter.cpp | |
index ceee9b6..679f540 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/interpreter/Interpreter.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/interpreter/Interpreter.cpp | |
@@ -1679,7 +1679,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi | |
JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue(); | |
JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue(); | |
+#if PLATFORM(WKC) | |
+ if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() > 0) { | |
+#else | |
if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0) { | |
+#endif | |
JSValue result = jsNumber(callFrame, dividend.asInt32() % divisor.asInt32()); | |
ASSERT(result); | |
callFrame->r(dst) = result; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/jit/JITStubs.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/jit/JITStubs.cpp | |
index fb7f931..4a8c5bc 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/jit/JITStubs.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/jit/JITStubs.cpp | |
@@ -1146,7 +1146,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_generic) | |
{ | |
STUB_INIT_STACK_FRAME(stackFrame); | |
- PutPropertySlot slot; | |
+ PutPropertySlot slot(stackFrame.callFrame->codeBlock()->putByIdContext()); | |
stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot); | |
CHECK_FOR_EXCEPTION_AT_END(); | |
} | |
@@ -1174,7 +1174,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id) | |
CallFrame* callFrame = stackFrame.callFrame; | |
Identifier& ident = stackFrame.args[1].identifier(); | |
- PutPropertySlot slot; | |
+ PutPropertySlot slot(stackFrame.callFrame->codeBlock()->putByIdContext()); | |
stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot); | |
CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); | |
@@ -1194,7 +1194,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_fail) | |
CallFrame* callFrame = stackFrame.callFrame; | |
Identifier& ident = stackFrame.args[1].identifier(); | |
- PutPropertySlot slot; | |
+ PutPropertySlot slot(stackFrame.callFrame->codeBlock()->putByIdContext()); | |
stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot); | |
CHECK_FOR_EXCEPTION_AT_END(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/parser/Lexer.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/parser/Lexer.cpp | |
index 15bda7b..2a269b8 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/parser/Lexer.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/parser/Lexer.cpp | |
@@ -142,19 +142,19 @@ void Lexer::setCode(const SourceCode& source, ParserArena& arena) | |
m_lastToken = -1; | |
const UChar* data = source.provider()->data(); | |
-#if PLATFORM(WKC) | |
- if (!data) { | |
- m_source = &source; | |
- const_cast<SourceCode*>(m_source)->invalidate(); | |
- m_codeStart = (UChar*)0; | |
- m_code = (UChar*)0; | |
- m_codeEnd = (UChar*)0; | |
- m_codeWithoutBOMs.shrink(0); | |
- m_error = true; | |
- m_atLineStart = true; | |
- m_current = m_next1 = m_next2 = m_next3 = -1; | |
- return; | |
- } | |
+#if PLATFORM(WKC) | |
+ if (!data) { | |
+ m_source = &source; | |
+ const_cast<SourceCode*>(m_source)->invalidate(); | |
+ m_codeStart = (UChar*)0; | |
+ m_code = (UChar*)0; | |
+ m_codeEnd = (UChar*)0; | |
+ m_codeWithoutBOMs.shrink(0); | |
+ m_error = true; | |
+ m_atLineStart = true; | |
+ m_current = m_next1 = m_next2 = m_next3 = -1; | |
+ return; | |
+ } | |
#endif | |
m_source = &source; | |
@@ -654,6 +654,8 @@ inStringEscapeSequence: | |
shiftLineTerminator(); | |
goto inString; | |
} | |
+ if (m_current == -1) | |
+ goto returnError; | |
record16(singleEscape(m_current)); | |
shift1(); | |
goto inString; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/ArrayPrototype.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/ArrayPrototype.cpp | |
index 13120dc..a121435 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/ArrayPrototype.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/ArrayPrototype.cpp | |
@@ -326,7 +326,10 @@ JSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue t | |
unsigned length = curArg.get(exec, exec->propertyNames().length).toUInt32(exec); | |
JSObject* curObject = curArg.toObject(exec); | |
for (unsigned k = 0; k < length; ++k) { | |
- if (JSValue v = getProperty(exec, curObject, k)) | |
+ JSValue v = getProperty(exec, curObject, k); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
+ if (v) | |
arr->put(exec, n, v); | |
n++; | |
} | |
@@ -388,7 +391,11 @@ JSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValue | |
for (unsigned k = 0; k < middle; k++) { | |
unsigned lk1 = length - k - 1; | |
JSValue obj2 = getProperty(exec, thisObj, lk1); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
JSValue obj = getProperty(exec, thisObj, k); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
if (obj2) | |
thisObj->put(exec, k, obj2); | |
@@ -415,7 +422,10 @@ JSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec, JSObject*, JSValue th | |
} else { | |
result = thisObj->get(exec, 0); | |
for (unsigned k = 1; k < length; k++) { | |
- if (JSValue obj = getProperty(exec, thisObj, k)) | |
+ JSValue obj = getProperty(exec, thisObj, k); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
+ if (obj) | |
thisObj->put(exec, k - 1, obj); | |
else | |
thisObj->deleteProperty(exec, k - 1); | |
@@ -464,7 +474,10 @@ JSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValue th | |
int b = static_cast<int>(begin); | |
int e = static_cast<int>(end); | |
for (int k = b; k < e; k++, n++) { | |
- if (JSValue v = getProperty(exec, thisObj, k)) | |
+ JSValue v = getProperty(exec, thisObj, k); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
+ if (v) | |
resObj->put(exec, n, v); | |
} | |
resObj->setLength(n); | |
@@ -498,10 +511,14 @@ JSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue thi | |
// or quicksort, and much less swapping than bubblesort/insertionsort. | |
for (unsigned i = 0; i < length - 1; ++i) { | |
JSValue iObj = thisObj->get(exec, i); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
unsigned themin = i; | |
JSValue minObj = iObj; | |
for (unsigned j = i + 1; j < length; ++j) { | |
JSValue jObj = thisObj->get(exec, j); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
double compareResult; | |
if (jObj.isUndefined()) | |
compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1) | |
@@ -574,7 +591,10 @@ JSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue t | |
deleteCount = length - begin; | |
for (unsigned k = 0; k < deleteCount; k++) { | |
- if (JSValue v = getProperty(exec, thisObj, k + begin)) | |
+ JSValue v = getProperty(exec, thisObj, k + begin); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
+ if (v) | |
resObj->put(exec, k, v); | |
} | |
resObj->setLength(deleteCount); | |
@@ -583,7 +603,10 @@ JSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue t | |
if (additionalArgs != deleteCount) { | |
if (additionalArgs < deleteCount) { | |
for (unsigned k = begin; k < length - deleteCount; ++k) { | |
- if (JSValue v = getProperty(exec, thisObj, k + deleteCount)) | |
+ JSValue v = getProperty(exec, thisObj, k + deleteCount); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
+ if (v) | |
thisObj->put(exec, k + additionalArgs, v); | |
else | |
thisObj->deleteProperty(exec, k + additionalArgs); | |
@@ -592,7 +615,10 @@ JSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue t | |
thisObj->deleteProperty(exec, k - 1); | |
} else { | |
for (unsigned k = length - deleteCount; k > begin; --k) { | |
- if (JSValue obj = getProperty(exec, thisObj, k + deleteCount - 1)) | |
+ JSValue obj = getProperty(exec, thisObj, k + deleteCount - 1); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
+ if (obj) | |
thisObj->put(exec, k + additionalArgs - 1, obj); | |
else | |
thisObj->deleteProperty(exec, k + additionalArgs - 1); | |
@@ -615,7 +641,10 @@ JSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec, JSObject*, JSValue | |
unsigned nrArgs = args.size(); | |
if (nrArgs) { | |
for (unsigned k = length; k > 0; --k) { | |
- if (JSValue v = getProperty(exec, thisObj, k - 1)) | |
+ JSValue v = getProperty(exec, thisObj, k - 1); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
+ if (v) | |
thisObj->put(exec, k + nrArgs - 1, v); | |
else | |
thisObj->deleteProperty(exec, k + nrArgs - 1); | |
@@ -672,6 +701,9 @@ JSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValue t | |
JSValue v = slot.getValue(exec, k); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
+ | |
MarkedArgumentBuffer eachArguments; | |
eachArguments.append(v); | |
@@ -725,12 +757,18 @@ JSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec, JSObject*, JSValue this | |
JSValue v = slot.getValue(exec, k); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
+ | |
MarkedArgumentBuffer eachArguments; | |
eachArguments.append(v); | |
eachArguments.append(jsNumber(exec, k)); | |
eachArguments.append(thisObj); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
+ | |
JSValue result = call(exec, function, callType, callData, applyThis, eachArguments); | |
resultArray->put(exec, k, result); | |
} | |
@@ -788,6 +826,9 @@ JSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValue th | |
eachArguments.append(jsNumber(exec, k)); | |
eachArguments.append(thisObj); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
+ | |
bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); | |
if (!predicateResult) { | |
@@ -839,6 +880,9 @@ JSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValue | |
eachArguments.append(jsNumber(exec, k)); | |
eachArguments.append(thisObj); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
+ | |
call(exec, function, callType, callData, applyThis, eachArguments); | |
} | |
return jsUndefined(); | |
@@ -887,6 +931,9 @@ JSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec, JSObject*, JSValue thi | |
eachArguments.append(jsNumber(exec, k)); | |
eachArguments.append(thisObj); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
+ | |
bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); | |
if (predicateResult) { | |
@@ -924,6 +971,8 @@ JSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec, JSObject*, JSValue t | |
} else { | |
for (i = 0; i < length; i++) { | |
rv = getProperty(exec, thisObj, i); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
if (rv) | |
break; | |
} | |
@@ -953,6 +1002,8 @@ JSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec, JSObject*, JSValue t | |
for (; i < length && !exec->hadException(); ++i) { | |
JSValue prop = getProperty(exec, thisObj, i); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
if (!prop) | |
continue; | |
@@ -994,6 +1045,8 @@ JSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec, JSObject*, JSVa | |
} else { | |
for (i = 0; i < length; i++) { | |
rv = getProperty(exec, thisObj, length - i - 1); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
if (rv) | |
break; | |
} | |
@@ -1022,6 +1075,8 @@ JSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec, JSObject*, JSVa | |
for (; i < length && !exec->hadException(); ++i) { | |
unsigned idx = length - i - 1; | |
JSValue prop = getProperty(exec, thisObj, idx); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
if (!prop) | |
continue; | |
@@ -1058,6 +1113,8 @@ JSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue | |
JSValue searchElement = args.at(0); | |
for (; index < length; ++index) { | |
JSValue e = getProperty(exec, thisObj, index); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
if (!e) | |
continue; | |
if (JSValue::strictEqual(exec, searchElement, e)) | |
@@ -1089,6 +1146,8 @@ JSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSVa | |
JSValue searchElement = args.at(0); | |
for (; index >= 0; --index) { | |
JSValue e = getProperty(exec, thisObj, index); | |
+ if (exec->hadException()) | |
+ return jsUndefined(); | |
if (!e) | |
continue; | |
if (JSValue::strictEqual(exec, searchElement, e)) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/Collector.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/Collector.cpp | |
index 7f083c6..1e726ee 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/Collector.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/Collector.cpp | |
@@ -1466,7 +1466,8 @@ static void setCollectorHeapStatistics(CollectorHeapStatistics& stat, int type, | |
unsigned int num = stat.numBlockInfo; | |
ASSERT(block); | |
- ASSERT(num < kMaxBlockInfo); | |
+ if (num >= kMaxBlockInfo) | |
+ return; | |
info = &stat.blockInfo[num]; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/Executable.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/Executable.cpp | |
index 2946221..71f5920 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/Executable.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/Executable.cpp | |
@@ -268,8 +268,10 @@ PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifi | |
return 0; | |
StatementNode* exprStatement = program->singleStatement(); | |
+#if !PLATFORM(WKC) | |
ASSERT(exprStatement); | |
ASSERT(exprStatement->isExprStatement()); | |
+#endif | |
if (!exprStatement || !exprStatement->isExprStatement()) | |
return 0; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/JSObject.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/JSObject.h | |
index a5da267..b91b5b0 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/JSObject.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/JSObject.h | |
@@ -501,7 +501,7 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue | |
if (specificFunction && m_structure->hasTransition(propertyName, attributes)) | |
specificFunction = 0; | |
- RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, specificFunction, offset); | |
+ RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, specificFunction, offset, slot.context()); | |
if (currentCapacity != structure->propertyStorageCapacity()) | |
allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity()); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/JSString.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/JSString.cpp | |
index 69164f8..fa19019 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/JSString.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/JSString.cpp | |
@@ -40,6 +40,8 @@ void JSString::Rope::destructNonRecursive() | |
unsigned length = rope->ropeLength(); | |
for (unsigned i = 0; i < length; ++i) { | |
Fiber& fiber = rope->fibers(i); | |
+ if (!fiber.string()) | |
+ continue; | |
if (fiber.isString()) | |
fiber.string()->deref(); | |
else { | |
@@ -117,6 +119,12 @@ void JSString::resolveRope(ExecState* exec) const | |
while (true) { | |
if (currentFiber.isRope()) { | |
Rope* rope = currentFiber.rope(); | |
+ if (rope->ropeLength()==0) { | |
+ for (unsigned i = 0; i < m_ropeLength; ++i) | |
+ m_fibers[i].deref(); | |
+ m_ropeLength = 0; | |
+ return; | |
+ } | |
// Copy the contents of the current rope into the workQueue, with the last item in 'currentFiber' | |
// (we will be working backwards over the rope). | |
unsigned ropeLengthMinusOne = rope->ropeLength() - 1; | |
@@ -126,8 +134,16 @@ void JSString::resolveRope(ExecState* exec) const | |
} else { | |
UString::Rep* string = currentFiber.string(); | |
unsigned length = string->size(); | |
- position -= length; | |
- copyChars(position, string->data(), length); | |
+ if (position-length >= buffer) { | |
+ position -= length; | |
+ copyChars(position, string->data(), length); | |
+ } else { | |
+ for (unsigned i = 0; i < m_ropeLength; ++i) | |
+ m_fibers[i].deref(); | |
+ m_ropeLength = 0; | |
+ throwOutOfMemoryError(exec); | |
+ return; | |
+ } | |
// Was this the last item in the work queue? | |
if (workQueue.isEmpty()) { | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/JSString.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/JSString.h | |
index 54e67d9..a9341c3 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/JSString.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/JSString.h | |
@@ -118,7 +118,11 @@ namespace JSC { | |
static PassRefPtr<Rope> createOrNull(unsigned ropeLength) | |
{ | |
void* allocation; | |
+#if PLATFORM(WKC) | |
+ if (tryFastZeroedMalloc(sizeof(Rope) + (ropeLength - 1) * sizeof(Fiber)).getValue(allocation)) | |
+#else | |
if (tryFastMalloc(sizeof(Rope) + (ropeLength - 1) * sizeof(Fiber)).getValue(allocation)) | |
+#endif | |
return adoptRef(new (allocation) Rope(ropeLength)); | |
return 0; | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/Operations.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/Operations.h | |
index c256b4b..680c29a 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/Operations.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/Operations.h | |
@@ -148,12 +148,9 @@ namespace JSC { | |
if (UNLIKELY(!rope)) | |
return throwOutOfMemoryError(exec); | |
-#if 1 // webkit.org trunk r54925 | |
- unsigned length = 0; | |
- bool overflow = false; | |
-#endif | |
+ unsigned oldLength = 0; | |
- unsigned index = 0; | |
+ unsigned int index = 0; | |
for (unsigned i = 0; i < count; ++i) { | |
JSValue v = strings[i].jsValue(); | |
if (LIKELY(v.isString())) | |
@@ -161,18 +158,10 @@ namespace JSC { | |
else | |
rope->append(index, v.toString(exec)); | |
-#if 1 // webkit.org trunk r54925 | |
- unsigned newLength = rope->ropeLength(); | |
- if (newLength < length) | |
- overflow = true; | |
- length = newLength; | |
- } | |
- | |
- if (overflow) | |
- return throwOutOfMemoryError(exec); | |
-#else | |
+ if (rope->stringLength() < oldLength) | |
+ return throwOutOfMemoryError(exec); | |
+ oldLength = rope->stringLength(); | |
} | |
-#endif | |
ASSERT(index == ropeLength); | |
return new (globalData) JSString(globalData, rope.release()); | |
@@ -197,16 +186,17 @@ namespace JSC { | |
if (UNLIKELY(!rope)) | |
return throwOutOfMemoryError(exec); | |
+ unsigned oldLength = 0; | |
+ | |
unsigned index = 0; | |
if (LIKELY(thisValue.isString())) | |
rope->append(index, asString(thisValue)); | |
else | |
rope->append(index, thisValue.toString(exec)); | |
-#if 1 // webkit.org trunk r54925 | |
- unsigned length = 0; | |
- bool overflow = false; | |
-#endif | |
+ if (rope->stringLength() < oldLength) | |
+ return throwOutOfMemoryError(exec); | |
+ oldLength = rope->stringLength(); | |
for (unsigned i = 0; i < args.size(); ++i) { | |
JSValue v = args.at(i); | |
@@ -214,18 +204,14 @@ namespace JSC { | |
rope->append(index, asString(v)); | |
else | |
rope->append(index, v.toString(exec)); | |
-#if 1 // webkit.org trunk r54925 | |
- unsigned newLength = rope->ropeLength(); | |
- if (newLength < length) | |
- overflow = true; | |
- length = newLength; | |
- } | |
- if (overflow) | |
- return throwOutOfMemoryError(exec); | |
-#else | |
+ if (rope->stringLength() < oldLength) { | |
+ rope.clear(); | |
+ return throwOutOfMemoryError(exec); | |
+ } | |
+ oldLength = rope->stringLength(); | |
} | |
-#endif | |
+ | |
ASSERT(index == ropeLength); | |
JSGlobalData* globalData = &exec->globalData(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/PutPropertySlot.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/PutPropertySlot.h | |
index eb8ea8a..22512de 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/PutPropertySlot.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/PutPropertySlot.h | |
@@ -37,10 +37,16 @@ namespace JSC { | |
class PutPropertySlot { | |
public: | |
enum Type { Uncachable, ExistingProperty, NewProperty }; | |
+#if !PLATFORM(WKC) | |
+ enum Context { UnknownContext, PutById, PutByIdEval }; | |
+#else | |
+ enum Context { UnknownContext, PutById, PutByIdEval, Contexts = 0x7fffffff }; | |
+#endif | |
- PutPropertySlot() | |
+ PutPropertySlot(Context context = UnknownContext) | |
: m_type(Uncachable) | |
, m_base(0) | |
+ , m_context(context) | |
{ | |
} | |
@@ -58,6 +64,8 @@ namespace JSC { | |
m_offset = offset; | |
} | |
+ Context context() const { return static_cast<Context>(m_context); } | |
+ | |
Type type() const { return m_type; } | |
JSObject* base() const { return m_base; } | |
@@ -70,6 +78,7 @@ namespace JSC { | |
Type m_type; | |
JSObject* m_base; | |
size_t m_offset; | |
+ uint8_t m_context; | |
}; | |
} // namespace JSC | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/Structure.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/Structure.cpp | |
index 0dbe7ca..e3dc291 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/Structure.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/Structure.cpp | |
@@ -410,7 +410,7 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct | |
return 0; | |
} | |
-PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset) | |
+PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset, PutPropertySlot::Context context) | |
{ | |
ASSERT(!structure->isDictionary()); | |
ASSERT(structure->typeInfo().type() == ObjectType); | |
@@ -422,7 +422,12 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con | |
specificValue = 0; | |
#endif | |
- if (structure->transitionCount() > s_maxTransitionLength) { | |
+ int maxTransitionLength; | |
+ if (context == PutPropertySlot::PutById) | |
+ maxTransitionLength = s_maxTransitionLengthForNonEvalPutById; | |
+ else | |
+ maxTransitionLength = s_maxTransitionLength; | |
+ if (structure->transitionCount() > maxTransitionLength) { | |
RefPtr<Structure> transition = toCacheableDictionaryTransition(structure); | |
ASSERT(structure != transition); | |
offset = transition->put(propertyName, attributes, specificValue); | |
@@ -506,7 +511,7 @@ PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structur | |
{ | |
#if 1 | |
// added at webkit.org trunk r52948 | |
- ASSERT(structure->m_specificFunctionThrashCount < maxSpecificFunctionThrashCount); | |
+// ASSERT(structure->m_specificFunctionThrashCount < maxSpecificFunctionThrashCount); | |
#endif | |
RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo()); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/Structure.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/Structure.h | |
index ce71210..a04c56f 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/Structure.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/Structure.h | |
@@ -33,6 +33,7 @@ | |
#include "PropertyMapHashTable.h" | |
#include "PropertyNameArray.h" | |
#include "Protect.h" | |
+#include "PutPropertySlot.h" | |
#include "StructureChain.h" | |
#include "StructureTransitionTable.h" | |
#include "JSTypeInfo.h" | |
@@ -66,7 +67,7 @@ namespace JSC { | |
static void dumpStatistics(); | |
- static PassRefPtr<Structure> addPropertyTransition(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); | |
+ static PassRefPtr<Structure> addPropertyTransition(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset, PutPropertySlot::Context = PutPropertySlot::UnknownContext); | |
static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); | |
static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset); | |
static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValue prototype); | |
@@ -195,6 +196,7 @@ namespace JSC { | |
static const unsigned emptyEntryIndex = 0; | |
static const signed char s_maxTransitionLength = 64; | |
+ static const int s_maxTransitionLengthForNonEvalPutById = 512; | |
static const signed char noOffset = -1; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/UString.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/UString.cpp | |
index 742b65b..3d37650 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/JavaScriptCore/runtime/UString.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/JavaScriptCore/runtime/UString.cpp | |
@@ -399,10 +399,18 @@ UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, in | |
} | |
int totalLength = 0; | |
- for (int i = 0; i < rangeCount; i++) | |
+ for (int i = 0; i < rangeCount; i++) { | |
+ if ((unsigned int)totalLength + (unsigned int)substringRanges[i].length > 0x7fffffff) { | |
+ return ""; | |
+ } | |
totalLength += substringRanges[i].length; | |
- for (int i = 0; i < separatorCount; i++) | |
+ } | |
+ for (int i = 0; i < separatorCount; i++) { | |
+ if ((unsigned int)totalLength + (unsigned int)separators[i].size() > 0x7fffffff) { | |
+ return ""; | |
+ } | |
totalLength += separators[i].size(); | |
+ } | |
if (totalLength == 0) | |
return ""; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/ChangeLog b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/ChangeLog | |
index bf59b0a..7b2ee9f 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/ChangeLog | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/ChangeLog | |
@@ -1,3 +1,2132 @@ | |
+2015-11-02 Jiewen Tan <jiewen_tan@apple.com> | |
+ | |
+ Null dereference loading Blink layout test fast/css/background-repeat-null-y-crash.html | |
+ https://bugs.webkit.org/show_bug.cgi?id=150211 | |
+ <rdar://problem/23137321> | |
+ | |
+ Reviewed by Alex Christensen. | |
+ | |
+ This is a merge of Blink r188842: | |
+ https://codereview.chromium.org/846933002 | |
+ | |
+ By setting the backgroundRepeatY property to null it can | |
+ happen that accessing that CSS value returns a null pointer. | |
+ In that case simply bail out early. | |
+ | |
+ Test: fast/css/background-repeat-null-y-crash.html | |
+ | |
+ * css/StyleProperties.cpp: | |
+ (WebCore::StyleProperties::getLayeredShorthandValue): | |
+ | |
+2014-10-17 Jeffrey Pfau <jpfau@apple.com> | |
+ | |
+ Ensure attached frame count doesn't exceed the maximum allowed frames | |
+ https://bugs.webkit.org/show_bug.cgi?id=136457 | |
+ | |
+ Reviewed by Alexey Proskuryakov. | |
+ | |
+ Test: fast/frames/exponential-frames.html | |
+ | |
+ * html/HTMLFrameElementBase.cpp: | |
+ (WebCore::HTMLFrameElementBase::isURLAllowed): | |
+ | |
+2014-05-07 Dean Jackson <dino@apple.com> | |
+ | |
+ Using a fill pattern much larger than actual canvas reliably segfaults browser | |
+ https://bugs.webkit.org/show_bug.cgi?id=132635 | |
+ | |
+ Reviewed by Simon Fraser. | |
+ | |
+ Make sure that createPattern checks that the canvas it is about to use | |
+ as a source is valid. | |
+ | |
+ Test: fast/canvas/pattern-too-large-to-create.html | |
+ | |
+ * html/canvas/CanvasRenderingContext2D.cpp: | |
+ (WebCore::CanvasRenderingContext2D::createPattern): Check that the source canvas has | |
+ an ok ImageBuffer. | |
+ | |
+2014-04-22 Zalan Bujtas <zalan@apple.com> | |
+ | |
+ Do not paint border image when the border rect is empty. | |
+ https://bugs.webkit.org/show_bug.cgi?id=131988 | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ http://trac.webkit.org/changeset/167351 introduced an early return when border | |
+ rect is empty. This patch ensures that border image is not painted either in that case. | |
+ | |
+ Modified padding-margin-negative-border.html to cover border-image case. | |
+ | |
+ * rendering/RenderBoxModelObject.cpp: | |
+ (WebCore::RenderBoxModelObject::paintBorder): | |
+ | |
+2014-04-11 Jon Honeycutt <jhoneycutt@apple.com> | |
+ | |
+ Assertion failure changing select element size during focus event | |
+ dispatch | |
+ <https://bugs.webkit.org/show_bug.cgi?id=131566> | |
+ <rdar://problem/16400735> | |
+ | |
+ Reviewed by Andy Estes. | |
+ | |
+ Test: fast/forms/select-change-size-during-focus.html | |
+ | |
+ * html/HTMLSelectElement.cpp: | |
+ (WebCore::HTMLSelectElement::listBoxDefaultEventHandler): | |
+ Adopt the fix from Chromium r171216; check that the renderer is still | |
+ of the expected type, and return early if it is not. | |
+ | |
+2014-03-21 Oliver Hunt <oliver@apple.com> | |
+ | |
+ Fix a crash when assigning an object to document.location | |
+ https://bugs.webkit.org/show_bug.cgi?id=130213 | |
+ | |
+ Reviewed by Geoffrey Garen. | |
+ | |
+ Convert location to string before we make use the document. | |
+ This prevents us from attempting to navigate a frame that | |
+ has already been removed. | |
+ | |
+ Test: fast/dom/navigation-with-sideeffects-crash.html | |
+ | |
+ * bindings/js/JSDocumentCustom.cpp: | |
+ (WebCore::JSDocument::location): | |
+ (WebCore::JSDocument::setLocation): | |
+ | |
+2013-08-14 Rob Buis <rwlbuis@webkit.org> | |
+ | |
+ Assertion failure in RenderObject::drawLineForBoxSide | |
+ https://bugs.webkit.org/show_bug.cgi?id=108187 | |
+ | |
+ Reviewed by David Hyatt. | |
+ | |
+ Don't draw the outline if the rectangle to draw is empty. | |
+ | |
+ Test: fast/css/outline-negative.html | |
+ | |
+ * rendering/RenderInline.cpp: | |
+ (WebCore::RenderInline::paintOutlineForLine): | |
+ | |
+2013-07-18 Santosh Mahto <santosh.ma@samsung.com> | |
+ | |
+ ASSERTION FAILED: !listItems().size() || m_activeSelectionAnchorIndex >= 0 in WebCore::HTMLSelectElement::updateListBoxSelection | |
+ https://bugs.webkit.org/show_bug.cgi?id=118591 | |
+ | |
+ Reviewed by Kent Tamura. | |
+ | |
+ Test: fast/forms/select/selectall-command-crash.html | |
+ | |
+ * html/HTMLSelectElement.cpp: | |
+ (WebCore::HTMLSelectElement::selectAll): | |
+ We should return this function if activeSelectionAnchorIndex is not valid index | |
+ | |
+2013-02-13 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ ASSERTION FAILED: !object || object->isBox(), Bad cast in RenderBox::computeLogicalHeight | |
+ https://bugs.webkit.org/show_bug.cgi?id=107748 | |
+ | |
+ Reviewed by Levi Weintraub. | |
+ | |
+ Make sure that body renderer is not an inline-block display | |
+ when determining that it stretches to viewport or when paginated | |
+ content needs base height. | |
+ | |
+ Test: fast/block/body-inline-block-crash.html | |
+ | |
+ * rendering/RenderBox.cpp: | |
+ (WebCore::RenderBox::computeLogicalHeight): | |
+ * rendering/RenderBox.h: | |
+ (WebCore::RenderBox::stretchesToViewport): | |
+ | |
+2013-02-11 Emil A Eklund <eae@chromium.org> | |
+ | |
+ Change RenderFrameSet::paint to use m-rows/m_cols directly. | |
+ https://bugs.webkit.org/show_bug.cgi?id=108503 | |
+ | |
+ Reviewed by Eric Seidel. | |
+ | |
+ Test: fast/frames/invalid-frameset.html | |
+ | |
+ * rendering/RenderFrameSet.cpp: | |
+ (WebCore::RenderFrameSet::paint): | |
+ | |
+2013-01-02 Douglas Stockwell <dstockwell@chromium.org> | |
+ | |
+ Crash in WebCore::InlineBox::deleteLine | |
+ https://bugs.webkit.org/show_bug.cgi?id=93448 | |
+ | |
+ Reviewed by Eric Seidel. | |
+ | |
+ When we ran off the end of the line while looking for line breaks in an | |
+ inline with white-space:nowrap nested in a block with white-space:pre | |
+ it was possible for the line break to be set at or before the current | |
+ position -- this could result in duplications in the render tree or | |
+ infinite looping. | |
+ | |
+ This patch changes the "fixup" logic that runs after we have finished | |
+ iterating through elements and text and have potentially found a break | |
+ point. In the case of a block setting white-space:pre we would back up | |
+ a character in some cases. Not doing so could leave whitespace that | |
+ should have been collapsed at the end of an inline. | |
+ | |
+ For example in '<span style="white-space:nowrap">x_</span>_y' if a | |
+ break was inserted before 'y' the space after 'x' would still be | |
+ rendered (rather than be collapsed with the break). | |
+ | |
+ To avoid this problem we will not take the opportunity to break until | |
+ we have finished collapsing whitespace. | |
+ | |
+ Tests: fast/text/whitespace/inline-whitespace-wrapping-1.html | |
+ fast/text/whitespace/inline-whitespace-wrapping-2.html | |
+ fast/text/whitespace/inline-whitespace-wrapping-3.html | |
+ fast/text/whitespace/inline-whitespace-wrapping-4.html | |
+ fast/text/whitespace/nowrap-white-space-collapse.html | |
+ fast/text/whitespace/pre-block-normal-inline-crash-1.html | |
+ fast/text/whitespace/pre-block-normal-inline-crash-2.html | |
+ | |
+ * rendering/RenderBlockLineLayout.cpp: | |
+ (WebCore::RenderBlock::LineBreaker::nextLineBreak): Collapse | |
+ whitespace before breaking. Avoid setting the break before the current | |
+ position. | |
+ | |
+2012-12-03 Hajime Morrita <morrita@google.com> | |
+ | |
+ Corrupted DOM tree during appendChild/insertBefore | |
+ https://bugs.webkit.org/show_bug.cgi?id=103601 | |
+ | |
+ Reviewed by Abhishek Arya. | |
+ | |
+ There are some missing protection in appendChild() and insertBefore(). | |
+ This change added these. | |
+ | |
+ Dromaeo dom-modify shows no speed regression (5445run/s before vs 5351run/s after) | |
+ | |
+ Tests: fast/events/mutation-during-append-child.html | |
+ fast/events/mutation-during-insert-before.html | |
+ | |
+ * dom/ContainerNode.cpp: | |
+ (WebCore::checkAcceptChildGuaranteedNodeTypes): | |
+ (WebCore): | |
+ (WebCore::ContainerNode::insertBefore): | |
+ (WebCore::ContainerNode::appendChild): | |
+ | |
+2012-11-25 Takashi Sakamoto <tasak@google.com> | |
+ | |
+ WebCore::RenderBlock::determineStartPosition crash | |
+ https://bugs.webkit.org/show_bug.cgi?id=98993 | |
+ | |
+ Reviewed by Brent Fulgham. | |
+ | |
+ If we move some node and the node has some text, | |
+ InlineFlowBox::removeChild() is invoked. The method invokes | |
+ RootInlineBox::childRemoved(). childRemoved() checks whether the | |
+ removed inlinebox has the renderer of its parent's line break object. | |
+ If so, use setLineBreakInfo to make the parent's line break info to | |
+ be 0. However in RenderBlock::determineStartPosition(), the code | |
+ assume that all line break info is solved, i.e. | |
+ prevRootBox->lineBreakObj()->isText(). Since lineBreakObj() returns 0 | |
+ because of removeChild(), determineStartPosition crash occurs. | |
+ | |
+ Test: fast/inline/inline-box-append-child-crash.html | |
+ | |
+ * rendering/RenderBlockLineLayout.cpp: | |
+ (WebCore::RenderBlock::determineStartPosition): | |
+ Checks whether lineBreakObj() is 0 or not before using lineBreakObj(). | |
+ | |
+2012-11-21 Daniel Bates <dbates@webkit.org> | |
+ | |
+ JavaScript fails to concatenate large strings | |
+ <https://bugs.webkit.org/show_bug.cgi?id=102963> | |
+ | |
+ Reviewed by Michael Saboff. | |
+ | |
+ Fixes an issue where we inadvertently didn't check the length of | |
+ a JavaScript string for overflow. | |
+ | |
+ * runtime/Operations.h: | |
+ (JSC::jsString): | |
+ (JSC::jsStringFromArguments): | |
+ | |
+2012-08-09 MORITA Hajime <morrita@google.com> | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=93587 | |
+ Node::replaceChild() can create bad DOM topology with MutationEvent, Part 2 | |
+ | |
+ Reviewed by Kent Tamura. | |
+ | |
+ This is a followup of r124156. replaceChild() has yet another hidden | |
+ MutationEvent trigger. This change added a guard for it. | |
+ | |
+ Test: fast/events/mutation-during-replace-child-2.html | |
+ | |
+ * dom/ContainerNode.cpp: | |
+ (WebCore::ContainerNode::replaceChild): | |
+ | |
+2012-07-30 MORITA Hajime <morrita@google.com> | |
+ | |
+ Node::replaceChild() can create bad DOM topology with MutationEvent | |
+ https://bugs.webkit.org/show_bug.cgi?id=92619 | |
+ | |
+ Reviewed by Ryosuke Niwa. | |
+ | |
+ Node::replaceChild() calls insertBeforeCommon() after dispatching | |
+ a MutationEvent event for removeChild(). But insertBeforeCommon() | |
+ expects call sites to check the invariant and doesn't have | |
+ suffient check. So a MutationEvent handler can let some bad tree | |
+ topology to slip into insertBeforeCommon(). | |
+ | |
+ This change adds a guard for checking the invariant using | |
+ checkReplaceChild() between removeChild() and insertBeforeCommon(). | |
+ | |
+ Test: fast/events/mutation-during-replace-child.html | |
+ | |
+ * dom/ContainerNode.cpp: | |
+ (WebCore::ContainerNode::replaceChild): Added a guard. | |
+ | |
+2012-05-10 Julien Chaffraix <jchaffraix@webkit.org> | |
+ | |
+ Crash in computedCSSPadding* functions due to RenderImage::imageDimensionsChanged called during attachment | |
+ https://bugs.webkit.org/show_bug.cgi?id=85912 | |
+ | |
+ Reviewed by Eric Seidel. | |
+ | |
+ Tests: fast/images/link-body-content-imageDimensionChanged-crash.html | |
+ fast/images/script-counter-imageDimensionChanged-crash.html | |
+ | |
+ The bug comes from CSS generated images that could end up calling imageDimensionsChanged during attachment. As the | |
+ rest of the code (e.g. computedCSSPadding*) would assumes that we are already inserted in the tree, we would crash. | |
+ | |
+ The solution is to bail out in this case as newly inserted RenderObject will trigger layout later on and properly | |
+ handle what we would be doing as part of imageDimensionChanged (the only exception being updating our intrinsic | |
+ size which should be done as part of imageDimensionsChanged). | |
+ | |
+ * rendering/RenderImage.cpp: | |
+ (WebCore::RenderImage::imageDimensionsChanged): | |
+ | |
+2012-02-29 Parag Radke <parag@motorola.com> | |
+ | |
+ Crash in WebCore::CompositeEditCommand::insertNodeAt | |
+ https://bugs.webkit.org/show_bug.cgi?id=67764 | |
+ | |
+ Reviewed by Ryosuke Niwa. | |
+ | |
+ If caret position after deletion and destination position coincides then | |
+ removing the node will result in removing the destination node also. Hence crash. | |
+ | |
+ Test: editing/deleting/delete-block-merge-contents-025.html | |
+ | |
+ * editing/CompositeEditCommand.cpp: | |
+ (WebCore::CompositeEditCommand::cleanupAfterDeletion): | |
+ If the caret position after delete and the destination position | |
+ renderes at the same place, pruning the node and making an early exit. | |
+ | |
+2012-02-06 Cris Neckar <cdn@chromium.org> | |
+ | |
+ Add RefPtrs for parent and sibling counter nodes | |
+ https://bugs.webkit.org/show_bug.cgi?id=75212 | |
+ | |
+ Reviewed by Adam Barth. | |
+ | |
+ Test: fast/css/counters/reparent-table-children-with-counters-crash.html | |
+ | |
+ * rendering/RenderCounter.cpp: | |
+ (WebCore::findPlaceForCounter): | |
+ (WebCore::makeCounterNode): | |
+ (WebCore::updateCounters): | |
+ | |
+2012-01-05 Kent Tamura <tkent@chromium.org> | |
+ | |
+ Fix a crash by importing an element of which local name ends with ":input". | |
+ https://bugs.webkit.org/show_bug.cgi?id=75103 | |
+ | |
+ Reviewed by Ryosuke Niwa. | |
+ | |
+ Test: fast/dom/importNode-confusing-localName.html | |
+ | |
+ * dom/Document.cpp: | |
+ (WebCore::Document::importNode): Pass QualifiedName of the source elemnt | |
+ to createElement() in order to avoid unnecessary serialization and | |
+ parsing of the qualified name | |
+ | |
+2011-11-18 Chris Evans <cevans@google.com> | |
+ | |
+ Crash with ranges across a detached, reparented node tree | |
+ https://bugs.webkit.org/show_bug.cgi?id=72757 | |
+ | |
+ Reviewed by Adam Barth. | |
+ | |
+ Test: fast/dom/move-detached-child-in-range.html | |
+ | |
+ * dom/RangeBoundaryPoint.h: | |
+ (WebCore::RangeBoundaryPoint::childBefore): protect the raw child node from getting pulled from under us. | |
+ | |
+2011-11-08 Chris Evans <cevans@google.com> | |
+ | |
+ Crash accessing font fact rule parent | |
+ https://bugs.webkit.org/show_bug.cgi?id=71860 | |
+ | |
+ Reviewed by Adam Barth. | |
+ | |
+ Test: fast/css/css-fontface-rule-crash.html | |
+ | |
+ * css/CSSFontFaceRule.cpp: | |
+ (WebCore::CSSFontFaceRule::~CSSFontFaceRule): tell our child rule when we are going away. | |
+ | |
+2011-09-27 Julien Chaffraix <jchaffraix@webkit.org> | |
+ | |
+ Crash because CSSPrimitiveValue::computeLengthDouble assumes fontMetrics are available | |
+ https://bugs.webkit.org/show_bug.cgi?id=66291 | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ Test: fast/canvas/crash-set-font.html | |
+ | |
+ This is Yet Another Missing updateFont (similar to bug 57756 and likely others). Here the issue is that | |
+ applying one of the font properties could mutate the parent style's font if m_parentStyle == m_style. | |
+ We would then query the newly created font when applying CSSPropertyFontSize, which has no font fallback | |
+ list as Font::update was never called. | |
+ | |
+ The right fix would be to refactor of how we handle fonts to avoid such manual updates (see bug 62390). | |
+ Until this happens, it is better not to crash. | |
+ | |
+ * css/CSSStyleSelector.cpp: | |
+ (WebCore::CSSStyleSelector::applyProperty): Added updateFont() here as the fonts could have been | |
+ mutated by the previous property change. Also added a comment explaining why it is safe to do it | |
+ this way. | |
+ | |
+2011-09-24 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Issues with merging block children of a ruby | |
+ base with another ruby base having inline children. | |
+ https://bugs.webkit.org/show_bug.cgi?id=66124 | |
+ | |
+ Reviewed by Dan Bernstein. | |
+ | |
+ Test: fast/ruby/ruby-base-merge-block-children-crash.html | |
+ | |
+ * rendering/RenderRubyBase.cpp: | |
+ (WebCore::RenderRubyBase::moveInlineChildren): add a firstChild() | |
+ check to prevent empty anonymous block addition, just like | |
+ moveBlockChildren method. | |
+ * rendering/RenderRubyBase.cpp: | |
+ (WebCore::RenderRubyBase::moveBlockChildren): This was incorrectly | |
+ doing optimizations to see if current ruby base has only inline | |
+ children before beforeChild and then trying to take out them from | |
+ their parent anonymous blocks. The problem is those inlines could | |
+ be split and have continuations because of encountering a block | |
+ inside inline flow. In those cases, we cannot take the inline out. | |
+ So, we should just make children non-inline in the destination | |
+ block and transfer the children as it-is. | |
+ * rendering/RenderRubyBase.h: remove unncessary functions. | |
+ | |
+2011-09-15 Julien Chaffraix <jchaffraix@webkit.org> | |
+ | |
+ Crash in RenderBox::paintMaskImages due to a mask without an associated image | |
+ https://bugs.webkit.org/show_bug.cgi?id=50151 | |
+ | |
+ Reviewed by Simon Fraser. | |
+ | |
+ Test: fast/css/empty-webkit-mask-crash.html | |
+ | |
+ The crash stems from the fact that FillLayer::hasImage would walk over the linked list | |
+ of FillLayers and return true if one had an image. This means that hasImage() is true | |
+ does not mean that image() is non-NULL on all FillLayers. | |
+ | |
+ * rendering/RenderBox.cpp: | |
+ (WebCore::RenderBox::paintMaskImages): Simplify the logic by doing the hasImage() check up-front | |
+ and properly check image() for each FillLayers. This has the nice benefit of changing the complexity | |
+ from O(n^2) to O(n), which was what the code expected anyway. | |
+ | |
+2011-08-30 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Style not updated for table parts in :before, :after content. | |
+ https://bugs.webkit.org/show_bug.cgi?id=66141 | |
+ | |
+ Reviewed by Dave Hyatt. | |
+ | |
+ Tests: fast/table/table-before-child-style-update.html | |
+ fast/table/table-row-before-child-style-update.html | |
+ | |
+ * rendering/RenderObjectChildList.cpp: | |
+ (WebCore::RenderObjectChildList::updateBeforeAfterContent): | |
+ | |
+2011-08-30 Tony Chang <tony@chromium.org> | |
+ | |
+ refactor box-ordinal-group handling so we don't timeout on large values | |
+ https://bugs.webkit.org/show_bug.cgi?id=65783 | |
+ | |
+ Reviewed by David Hyatt. | |
+ | |
+ The old code walked from 1 to the last box-ordinal-group while | |
+ iterating over each flex item. The new code collects ordinals as | |
+ we do the first walk and sorts them. Each additional iteration | |
+ through the flex items gets the next oridnal from the sorted list. | |
+ | |
+ This maintains the single pass for the common case of no | |
+ box-ordinal-groups specified. If there are ordinal groups, | |
+ the runtime is O(n*m + m lg m) where n is the # of flex items and | |
+ m is the number of unique box-ordinal-group values. The memory | |
+ usage is O(2m). | |
+ | |
+ Test: fast/flexbox/box-ordinal-group.html | |
+ | |
+ * rendering/RenderDeprecatedFlexibleBox.cpp: | |
+ (WebCore::FlexBoxIterator::FlexBoxIterator): | |
+ (WebCore::FlexBoxIterator::reset): | |
+ (WebCore::FlexBoxIterator::next): | |
+ (WebCore::FlexBoxIterator::compareFlexOrder): | |
+ | |
+2011-08-25 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Incorrect layout of :before and :after content, with display | |
+ table, table-row and table-cell. | |
+ https://bugs.webkit.org/show_bug.cgi?id=66699 | |
+ | |
+ Reviewed by David Hyatt. | |
+ | |
+ Tests: fast/table/table-after-child-in-table.html | |
+ fast/table/table-before-child-in-table.html | |
+ fast/table/table-cell-after-child-in-block.html | |
+ fast/table/table-cell-after-child-in-table.html | |
+ fast/table/table-cell-before-child-in-block.html | |
+ fast/table/table-cell-before-child-in-table.html | |
+ fast/table/table-row-after-child-in-block.html | |
+ fast/table/table-row-after-child-in-table.html | |
+ fast/table/table-row-before-child-in-block.html | |
+ fast/table/table-row-before-child-in-table.html | |
+ | |
+ * rendering/RenderBlock.cpp: | |
+ (WebCore::RenderBlock::addChildIgnoringAnonymousColumnBlocks): | |
+ Fix the looping condition to detect :after child correctly. | |
+ isAnonymousBlock() does not apply to tables, instead | |
+ using isAnonymous(). | |
+ * rendering/RenderTableRow.cpp: | |
+ (WebCore::RenderTableRow::addChild): Don't add the new child | |
+ in the generatedContainer with :before, :after content. | |
+ * rendering/RenderTableSection.cpp: | |
+ (WebCore::RenderTableSection::addChild): Don't add the new child | |
+ in the generatedContainer with :before, :after content. | |
+ | |
+2011-08-20 Darin Adler <darin@apple.com> | |
+ | |
+ If Range::insertNode is passed an empty document fragment, it creates a broken DOM tree | |
+ https://bugs.webkit.org/show_bug.cgi?id=65015 | |
+ | |
+ Reviewed by Alexey Proskuryakov. | |
+ | |
+ Test: fast/dom/Range/insertNode-empty-fragment-crash.html | |
+ | |
+ * dom/Range.cpp: (WebCore::Range::insertNode): Don't adjust the range after insertion | |
+ if we didn't add anything. Otherwise the code will put a wrong "child before" value into | |
+ the range end boundary point. | |
+ | |
+2011-08-11 Cris Neckar <cdn@chromium.org> | |
+ | |
+ Fixes several bugs when adding CounterNodes to a tree which can cause asymetrical relationships. | |
+ https://bugs.webkit.org/show_bug.cgi?id=65996 | |
+ | |
+ Reviewed by Eric Seidel. | |
+ | |
+ Test: fast/css/counters/counter-reparent-table-children-crash.html | |
+ | |
+ * rendering/CounterNode.cpp: | |
+ (WebCore::CounterNode::insertAfter): | |
+ * rendering/RenderCounter.cpp: | |
+ (WebCore::findPlaceForCounter): | |
+ (WebCore::makeCounterNode): | |
+ | |
+2011-07-29 Emil A Eklund <eae@chromium.org> | |
+ | |
+ -webkit-marquee with anonymous node causes segmentation fault in Node::document | |
+ https://bugs.webkit.org/show_bug.cgi?id=64693 | |
+ | |
+ Reviewed by Simon Fraser. | |
+ | |
+ Test: fast/css/webkit-marquee-anonymous-node-crash.html | |
+ | |
+ * rendering/RenderLayer.cpp: | |
+ (WebCore::RenderLayer::scrollTo): | |
+ Add null check as renderer()->node() is null for anonymous nodes. | |
+ | |
+2011-07-27 Ryosuke Niwa <rniwa@webkit.org> | |
+ | |
+ Calling window.find immediately after mutating the document crashes WebKit. | |
+ https://bugs.webkit.org/show_bug.cgi?id=65296 | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ Don't forget to layout first. | |
+ | |
+ Test: editing/text-iterator/find-after-mutation.html | |
+ | |
+ * editing/TextIterator.cpp: | |
+ (WebCore::findPlainText): | |
+ | |
+2011-07-20 Tony Chang <tony@chromium.org> | |
+ | |
+ Stale pointer due to floats not removed (flexible box display) | |
+ https://bugs.webkit.org/show_bug.cgi?id=64603 | |
+ | |
+ Reviewed by David Hyatt. | |
+ | |
+ Flexbox items should avoid floats. | |
+ | |
+ Test: fast/flexbox/horizontal-box-float-crash.html | |
+ | |
+ * rendering/RenderBox.cpp: | |
+ (WebCore::RenderBox::avoidsFloats): | |
+ * rendering/RenderBox.h: | |
+ (WebCore::RenderBox::isDeprecatedFlexItem): | |
+ | |
+2011-07-13 MORITA Hajime <morrita@google.com> | |
+ | |
+ Refactoring: Ignored ExceptionCode value should be less annoying. | |
+ https://bugs.webkit.org/show_bug.cgi?id=63688 | |
+ | |
+ - Introduced ExceptionCodePlaceholder class for the default parameter of ExceptionCode. | |
+ - Introduced ASSERT_NO_EXCEPTION to check ExceptionCode not set to non-zero after the call. | |
+ - Adopted ASSERT_NO_EXCEPTION in Range.cpp | |
+ | |
+ No new tests. No behaviour change. | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ * GNUmakefile.list.am: | |
+ * WebCore.gypi: | |
+ * WebCore.xcodeproj/project.pbxproj: | |
+ * dom/ExceptionCodePlaceholder.h: Added. | |
+ (WebCore::ExceptionCodePlaceholder::ExceptionCodePlaceholder): | |
+ (WebCore::ExceptionCodePlaceholder::operator ExceptionCode& ): | |
+ (WebCore::IgnorableExceptionCode::IgnorableExceptionCode): | |
+ (WebCore::CheckedExceptionCode::CheckedExceptionCode): | |
+ (WebCore::CheckedExceptionCode::~CheckedExceptionCode): | |
+ * dom/Range.cpp: | |
+ (WebCore::Range::Range): | |
+ (WebCore::Range::editingStartPosition): | |
+ * dom/Range.h: | |
+ | |
+2011-06-30 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Reviewed by Ryosuke Niwa. | |
+ | |
+ Crash when calling DOMSubtreeModified event when extracting range | |
+ contents. | |
+ https://bugs.webkit.org/show_bug.cgi?id=63650 | |
+ | |
+ Convert a few nodes to RefPtrs and add commonRoot verification checks | |
+ for Range::processContents. | |
+ | |
+ Tests: fast/dom/Range/range-extract-contents-event-fire-crash.html | |
+ fast/dom/Range/range-extract-contents-event-fire-crash2.html | |
+ | |
+ * dom/Range.cpp: | |
+ (WebCore::childOfCommonRootBeforeOffset): | |
+ (WebCore::Range::processContents): | |
+ (WebCore::Range::processContentsBetweenOffsets): | |
+ (WebCore::Range::processAncestorsAndTheirSiblings): | |
+ | |
+2011-06-29 Darin Adler <darin@apple.com> | |
+ | |
+ Reviewed by Anders Carlsson. | |
+ | |
+ [WebKit2] Crash loading page that adds/removes frame in DOMContentLoaded/loaded | |
+ https://bugs.webkit.org/show_bug.cgi?id=63483 | |
+ | |
+ Test: fast/loader/create-frame-in-DOMContentLoaded.html | |
+ | |
+ * loader/FrameLoader.cpp: | |
+ (WebCore::FrameLoader::init): Added an assertion. | |
+ (WebCore::FrameLoader::finishedLoadingDocument): Removed a non-helpful #if | |
+ statement. The rule that we do not call the client when creating the initial | |
+ empty document was nominally specific to Windows and Chromium but is needed | |
+ for all platforms. | |
+ | |
+2011-06-28 Roland Steiner <rolandsteiner@chromium.org> | |
+ | |
+ Reviewed by Eric Seidel. | |
+ | |
+ Bug 55930 - (CVE-2011-1440) Incorrect handling of 'display:' property within nested <ruby> tags | |
+ https://bugs.webkit.org/show_bug.cgi?id=55930 | |
+ | |
+ Don't set style type BEFORE/AFTER on anonymous wrapper block. | |
+ Rather, check style type on generated wrapped child. | |
+ | |
+ Tests: fast/ruby/generated-after-counter-doesnt-crash.html | |
+ fast/ruby/generated-before-and-after-counter-doesnt-crash.html | |
+ fast/ruby/generated-before-counter-doesnt-crash.html | |
+ | |
+ * rendering/RenderRuby.cpp: | |
+ (WebCore::isAnonymousRubyInlineBlock): | |
+ (WebCore::isRubyBeforeBlock): | |
+ (WebCore::isRubyAfterBlock): | |
+ (WebCore::rubyBeforeBlock): | |
+ (WebCore::rubyAfterBlock): | |
+ (WebCore::createAnonymousRubyInlineBlock): | |
+ (WebCore::RenderRubyAsInline::addChild): | |
+ (WebCore::RenderRubyAsBlock::addChild): | |
+ | |
+2011-05-31 Yong Li <yoli@rim.com> | |
+ | |
+ Reviewed by Eric Seidel. | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=54807 | |
+ We have been assuming plain bitfields (like "int a : 31") are always signed integers. | |
+ However some compilers can treat them as unsigned. For example, RVCT 4.0 states plain | |
+ bitfields (declared without either signed or unsigned qualifiers) are treats as unsigned. | |
+ http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0348c/Babjddhe.html | |
+ Although we can use "--signed-bitfields" flag to make RVCT 4.0 behave as most other compilers, | |
+ always using "signed"/"unsigned" qualifier to declare integral type bitfields is still a good | |
+ rule we should have in order to make our code independent from compilers and compiler flags. | |
+ | |
+ No new test added because this change is not known to fix any issue. | |
+ | |
+ * css/CSSPrimitiveValue.h: | |
+ * css/CSSProperty.h: | |
+ * rendering/InlineBox.h: | |
+ * rendering/RenderBlock.h: | |
+ | |
+2011-04-13 Roland Steiner <rolandsteiner@chromium.org> | |
+ | |
+ Reviewed by David Hyatt. | |
+ | |
+ Bug 55930 - Incorrect handling of 'display:' property within nested <ruby> tags | |
+ https://bugs.webkit.org/show_bug.cgi?id=55930 | |
+ | |
+ Non-inline :before/:after generated content is now wrapped with an anonymous inline block. | |
+ | |
+ Also, added an additional check in RenderObjectChildList::updateBeforeAfterContent() | |
+ to verify that the created render object is legal under the parent. | |
+ | |
+ Tests: fast/ruby/after-block-doesnt-crash.html | |
+ fast/ruby/after-table-doesnt-crash.html | |
+ fast/ruby/before-block-doesnt-crash.html | |
+ fast/ruby/before-table-doesnt-crash.html | |
+ | |
+ * rendering/RenderObjectChildList.cpp: | |
+ (WebCore::RenderObjectChildList::updateBeforeAfterContent): | |
+ * rendering/RenderRuby.cpp: | |
+ (WebCore::isAnonymousRubyInlineBlock): | |
+ (WebCore::rubyBeforeBlock): | |
+ (WebCore::rubyAfterBlock): | |
+ (WebCore::createAnonymousRubyInlineBlock): | |
+ (WebCore::lastRubyRun): | |
+ (WebCore::RenderRubyAsInline::addChild): | |
+ (WebCore::RenderRubyAsInline::removeChild): | |
+ (WebCore::RenderRubyAsBlock::addChild): | |
+ (WebCore::RenderRubyAsBlock::removeChild): | |
+ * rendering/RenderRuby.h: | |
+ | |
+2011-03-30 Dan Bernstein <mitz@apple.com> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ <rdar://problem/9199518> Crash when focusing a styled editable element | |
+ | |
+ Test: editing/deleting/delete-button-background-image-none.html | |
+ | |
+ * editing/DeleteButtonController.cpp: | |
+ (WebCore::isDeletableElement): Check all background layers for background images. | |
+ * rendering/style/RenderStyle.h: Removed backgroundImage() as it was only used, incorrectly, | |
+ in the above function. | |
+ | |
+2011-03-10 Alice Boxhall <aboxhall@chromium.org> | |
+ | |
+ Reviewed by Dimitri Glazkov. | |
+ | |
+ NULL pointer crash when using :empty and :first-line pseudoclass selectors together | |
+ https://bugs.webkit.org/show_bug.cgi?id=53316 | |
+ | |
+ :empty is calculated for each element during parsing, but then not | |
+ recalculated after any child elements are attached. Force style | |
+ re-calculation on elements which have :empty in their style when | |
+ their children are changed. | |
+ | |
+ Test: fast/css/empty-first-line-crash.html | |
+ | |
+ * dom/Element.cpp: | |
+ (WebCore::checkForEmptyStyleChange): Pull out empty style checking | |
+ logic from checkForSiblingStyleChanges(). | |
+ (WebCore::checkForSiblingStyleChanges): Use new checkForEmptyStyleChanges() | |
+ method. | |
+ (WebCore::Element::childrenChanged): Call checkForEmptyStyleChanges() when | |
+ called with changedByParser = true. | |
+ | |
+2011-03-09 Dan Bernstein <mitz@apple.com> | |
+ | |
+ Reviewed by Dave Hyatt. | |
+ | |
+ <rdar://problem/8733254> Float disappears after incremental layout | |
+ Fixed the original bug and a copule more issues noticed while doing so. | |
+ | |
+ Tests: fast/dynamic/dirty-float-in-clean-line.html | |
+ fast/dynamic/float-at-line-break.html | |
+ fast/dynamic/float-from-empty-line.html | |
+ | |
+ * rendering/RenderBlock.h: | |
+ * rendering/RenderBlockLineLayout.cpp: | |
+ (WebCore::RenderBlock::layoutInlineChildren): If findNextLineBreak() returned an empty line, | |
+ update the line break info of the last line with the new line break position. This is tested | |
+ by float-from-empty-line.html. | |
+ (WebCore::RenderBlock::checkFloatsInCleanLine): Factored out code from determineStartPosition() | |
+ into this new function. | |
+ (WebCore::RenderBlock::determineStartPosition): Call checkFloatsInCleanLine(). | |
+ (WebCore::RenderBlock::determineEndPosition): When iterating over lines, check clean lines with | |
+ floats, as they may yet become dirty because of the floats. This is tested by | |
+ dirty-float-in-clean-line.html. | |
+ (WebCore::RenderBlock::findNextLineBreak): If a float fits on the line, and the current line | |
+ break is at the float, advance it to after the float. Otherwise, if the line gets dirty and the | |
+ next one does not, the float will not make it into any line. This is tested by | |
+ float-at-line-break.html. | |
+ | |
+2011-02-01 chris reiss <christopher.reiss@nokia.com> | |
+ | |
+ Reviewed by Adam Barth. | |
+ | |
+ Self-replicating code makes Safari hang and eventually crash | |
+ https://bugs.webkit.org/show_bug.cgi?id=15123 | |
+ | |
+ | |
+ Here we are replicating the Firefox safeguard against | |
+ recursive document.write( ) 's. | |
+ | |
+ See https://bug197052.bugzilla.mozilla.org/attachment.cgi?id=293907 in bug | |
+ https://bugzilla.mozilla.org/show_bug.cgi?id=197052 . Firefox does two things - | |
+ a) imposes a recursion limit of 20 on document.write( ) and | |
+ b) once that limit is passed, panics all the way the call stack (rather than just returning one level.) | |
+ To see why this is necessary, consider the script : | |
+ | |
+ <script> | |
+ var t = document.body.innerHTML; | |
+ document.write(t); | |
+ </script> | |
+ | |
+ This will create a tree both broad and deep as the script keeps appending itself to the text. If | |
+ we just return one level after the recursion limit is reached, we still allow millions of copies to | |
+ duplicate (and execute). | |
+ | |
+ The recursion is fortunately depth-first, so as soon as we cross this limit, we panic up the callstack | |
+ to prevent this situation. (IE apparently does the same thing, with a lower recursion limit.) | |
+ | |
+ Test: fast/dom/Document/document-write-recursion.html | |
+ Test: fast/dom/Document/document-close-iframe-load.html | |
+ Test: fast/dom/Document/document-close-nested-iframe-load.html | |
+ | |
+ | |
+ * dom/Document.cpp: | |
+ (WebCore::Document::Document): | |
+ (WebCore::Document::write): | |
+ * dom/Document.h: | |
+ | |
+2011-01-20 James Robinson <jamesr@chromium.org> | |
+ | |
+ Reviewed by Eric "Baller" Seidel. | |
+ | |
+ RenderTableSection's setNeedsCellRecalc needs to null check table() | |
+ https://bugs.webkit.org/show_bug.cgi?id=52770 | |
+ | |
+ Null checks table() before deferencing it in RenderTableSection::setNeedsCellRecalc. | |
+ This can be null during detach(). Test constructed by Eric Seidel. | |
+ | |
+ Test: fast/css-generated-content/table-with-scrollbar-corner.html | |
+ | |
+ * rendering/RenderTableSection.cpp: | |
+ (WebCore::RenderTableSection::setNeedsCellRecalc): | |
+ * rendering/RenderTableSection.h: | |
+ | |
+2011-01-20 Xiaomei Ji <xji@chromium.org> | |
+ | |
+ Reviewed by Dan Bernstein. | |
+ | |
+ Fix regression(r71566): PDF in RTL block might messes up text directionality. | |
+ https://bugs.webkit.org/show_bug.cgi?id=52776 | |
+ | |
+ Test: fast/dom/52776.html | |
+ | |
+ * platform/text/BidiResolver.h: | |
+ (WebCore::::checkDirectionInLowerRaiseEmbeddingLevel): | |
+ (WebCore::::lowerExplicitEmbeddingLevel): | |
+ (WebCore::::raiseExplicitEmbeddingLevel): | |
+ (WebCore::::createBidiRunsForLine): | |
+ | |
+2011-01-19 Yuzo Fujishima <yuzo@google.com> | |
+ | |
+ Reviewed by Kent Tamura. | |
+ | |
+ Fix for Bug 52279 - WebCore::RenderBlock::updateFirstLetter crashes for anonymous blocks | |
+ https://bugs.webkit.org/show_bug.cgi?id=52279 | |
+ | |
+ In constructing text fragments to handle first-letter rule, first add | |
+ the text for the non-first letters and then remove the original text, | |
+ rather than the other way around. Otherwise, the text can be added to | |
+ an anoymous block that is different from the original one. This breaks | |
+ the assumption that a first letter render object has a non-null sibling | |
+ for the non-first letters and causes a crash. | |
+ | |
+ Test: fast/css/first-letter-anonymous-block-crash.html | |
+ | |
+ * rendering/RenderBlock.cpp: | |
+ (WebCore::RenderBlock::updateFirstLetter): | |
+ | |
+2011-01-14 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Reviewed by David Hyatt. | |
+ | |
+ Prevent merging of anonymous blocks if one of them is already getting | |
+ destroyed. | |
+ https://bugs.webkit.org/show_bug.cgi?id=52402 | |
+ | |
+ Test: fast/block/merge-anonymous-block-remove-child-crash2.html | |
+ | |
+ * rendering/RenderBlock.cpp: | |
+ (WebCore::RenderBlock::RenderBlock): initialize m_beingDestroyed to false. | |
+ (WebCore::RenderBlock::destroy): set m_beingDestroyed to true. | |
+ (WebCore::canMergeContiguousAnonymousBlocks): do not merge if any or prev or next is being destroyed. | |
+ (WebCore::RenderBlock::removeChild): remove the hack previously done for preventing oldChild merging with nextBlock's next sibling. | |
+ * rendering/RenderBlock.h: | |
+ (WebCore::RenderBlock::beingDestroyed): public function for m_beingDestroyed. | |
+ | |
+2011-01-11 Simon Fraser <simon.fraser@apple.com> | |
+ | |
+ Reviewed by Dan Bernstein. | |
+ | |
+ Webkit crashes when a gradient is applied using the first-line pseudo element | |
+ https://bugs.webkit.org/show_bug.cgi?id=52225 | |
+ | |
+ When a pseudostyle references images, we fail to register/unregister | |
+ the relevant RenderObjects as clients of the image in the style. | |
+ For gradients, this caused a crash. | |
+ | |
+ This patch fixes the crash by returning a null gradient image in this | |
+ situation. | |
+ | |
+ Test: fast/gradients/gradient-on-pseudoelement-crash.html | |
+ | |
+ * css/CSSGradientValue.cpp: | |
+ (WebCore::CSSGradientValue::image): | |
+ | |
+2011-01-11 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Reviewed by Dimitri Glazkov. | |
+ | |
+ RefPtr the FrameView to prevent scrollbar from getting deleted inside | |
+ its scroll event. | |
+ https://bugs.webkit.org/show_bug.cgi?id=52238 | |
+ | |
+ Test: scrollbars/scrollable-iframe-remove-crash.html | |
+ | |
+ * page/DOMWindow.cpp: | |
+ (WebCore::DOMWindow::scrollTo): | |
+ | |
+2010-12-29 Tony Gentilcore <tonyg@chromium.org> | |
+ | |
+ Reviewed by Eric Seidel. | |
+ | |
+ Assertion failure: element->inDocument() in AsyncScriptRunner::executeScriptSoon() | |
+ https://bugs.webkit.org/show_bug.cgi?id=51067 | |
+ | |
+ Typically when a script element is removed from the document, the cached script | |
+ client is removed. However, during the before load event, the cached script client | |
+ hasn't been created yet so it can't be removed. | |
+ | |
+ This patch handles that case by explicitly checking if the script element was | |
+ removed during the beforeload event. Also, it avoids caching the Document references | |
+ over the arbitrary script execution in the before load event. | |
+ | |
+ Test: fast/dom/HTMLScriptElement/move-in-beforeload.html | |
+ fast/dom/HTMLScriptElement/remove-in-beforeload.html | |
+ | |
+ * dom/ScriptElement.cpp: | |
+ (WebCore::ScriptElement::requestScript): | |
+ | |
+2010-12-15 Yong Li <yoli@rim.com> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ Fix stack overflow when there are too many sibling inline boxes by using | |
+ a loop to traverse children instead of calling each sibling from the first child. | |
+ https://bugs.webkit.org/show_bug.cgi?id=48255 | |
+ | |
+ Test: fast/overflow/lots-of-sibling-inline-boxes.html | |
+ | |
+ * rendering/InlineBox.h: | |
+ (WebCore::InlineBox::setConstructed): | |
+ (WebCore::InlineBox::next): | |
+ * rendering/InlineFlowBox.h: | |
+ (WebCore::InlineFlowBox::setConstructed): | |
+ | |
+2010-12-14 Emil Eklund <eae@chromium.org> | |
+ | |
+ Reviewed by NOBODY (OOPS!). | |
+ | |
+ Change ContainerNode::willRemoveChildren to not fire mutation events for children | |
+ added as a result of a mutation event, thereby avoiding an infinite loop. | |
+ https://bugs.webkit.org/show_bug.cgi?id=51079 | |
+ | |
+ Test: fast/dom/containerNode.html | |
+ | |
+ * dom/ContainerNode.cpp: | |
+ (WebCore::willRemoveChildren): Don't fire mutation events for children added during a mutation event. | |
+ | |
+2010-12-10 Emil Eklund <eae@chromium.org> | |
+ | |
+ Reviewed by Adam Barth. | |
+ | |
+ Fix crash in Range::processContents when modified during mutation event. | |
+ https://bugs.webkit.org/show_bug.cgi?id=50710 | |
+ | |
+ Test: fast/dom/Range/range-extractContents.html | |
+ | |
+ * dom/Range.cpp: | |
+ (WebCore::Range::processContents): | |
+ Replace raw pointers with RefPtrs and add checks. | |
+ | |
+2010-12-09 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Reviewed by Dimitri Glazkov. | |
+ | |
+ As part of r73559, I added the referenceNode check to validate whether the root | |
+ node of the iterator matches the node which is getting moved to other document. | |
+ referenceNode is initialized to root, however can get moved using previousNode | |
+ and nextNode methods, so it is required to use root directly. | |
+ https://bugs.webkit.org/show_bug.cgi?id=50764 | |
+ | |
+ Test: fast/dom/node-iterator-reference-node-moved-crash.html | |
+ | |
+ * dom/Document.cpp: | |
+ (WebCore::Document::moveNodeIteratorsToNewDocument): change referenceNode to root. | |
+ | |
+2010-12-08 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Reviewed by Dimitri Glazkov. | |
+ | |
+ Detach node iterator and move to new document when node gets moved. | |
+ https://bugs.webkit.org/show_bug.cgi?id=50697 | |
+ | |
+ Test: fast/dom/node-iterator-document-moved-crash.html | |
+ | |
+ * dom/Document.cpp: Method that takes a node and new document as argument. | |
+ It detaches the node iterators belonging to the current document and attaches | |
+ them to the new document. | |
+ (WebCore::Document::moveNodeIteratorsToNewDocument): | |
+ * dom/Document.h: Function definition. | |
+ * dom/Node.cpp: When node is moved to another document, call the function to move | |
+ the iterators appropriately. | |
+ (WebCore::Node::setDocument): | |
+ | |
+2010-11-30 Alexey Proskuryakov <ap@apple.com> | |
+ | |
+ Reviewed by Darin Adler and Geoff Garen. | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=44152 | |
+ <rdar://problem/8324423> CSSOM should match DOM in discarding wrapper-less parents. | |
+ | |
+ We have existing behaviors where parent objects in detached subtrees are not preserved: | |
+ - if a root of a node tree doesn't have a wrapper, it's immediately destroyed, making | |
+ its children parentNode attribute null; | |
+ - relationship between a <style> or <link> node and its stylesheet is immediately broken | |
+ when the node is removed from document (in this case, regardless of wrapper existence). | |
+ | |
+ Both match Firefox. For consistency, CSSOM should do the same. In fact, it already partially | |
+ does - CSSRule.parentRule gets zeroed out when the parent rule is destroyed. | |
+ | |
+ Tests: fast/dom/StyleSheet/detached-parent-rule-without-wrapper.html | |
+ fast/dom/StyleSheet/detached-stylesheet-without-wrapper.html | |
+ | |
+ * css/StyleSheet.cpp: (WebCore::StyleSheet::~StyleSheet): Clear out child rule parent. | |
+ | |
+ * svg/SVGFontFaceElement.cpp: (WebCore::SVGFontFaceElement::insertedIntoDocument): Keep | |
+ the new assertion from firing. This function was adding a rule to style sheet, without | |
+ telling the rule about it. | |
+ | |
+2010-11-29 Alexey Proskuryakov <ap@apple.com> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=50165 | |
+ CSS style rules don't GC protect parents | |
+ | |
+ Tests: fast/dom/StyleSheet/gc-parent-rule.html | |
+ fast/dom/StyleSheet/gc-parent-stylesheet.html | |
+ | |
+ * bindings/js/JSCSSRuleCustom.cpp: (WebCore::JSCSSRule::markChildren): Mark parents. The code | |
+ is super naive compared to what we have for nodes - but CSSOM has shallow hierarchies, so | |
+ it should be OK. | |
+ | |
+ * css/CSSRule.idl: Added CustomMarkFunction. | |
+ | |
+2010-11-23 Cris Neckar <cdn@chromium.org> | |
+ | |
+ Reviewed by Dimitri Glazkov. | |
+ | |
+ Removed unneeded conversions to RenderBlock. | |
+ https://bugs.webkit.org/show_bug.cgi?id=49896 | |
+ | |
+ Test: fast/css/input-search-table-column-crash.html | |
+ | |
+ * rendering/RenderTextControlSingleLine.cpp: | |
+ (WebCore::RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight): | |
+ | |
+2010-11-08 Alexander Pavlov <apavlov@chromium.org> | |
+ | |
+ Reviewed by David Hyatt. | |
+ | |
+ getPropertyValue("background") causes crash | |
+ https://bugs.webkit.org/show_bug.cgi?id=49055 | |
+ | |
+ Test: fast/css/background-norepeat-crash.html | |
+ | |
+ * css/CSSMutableStyleDeclaration.cpp: | |
+ (WebCore::CSSMutableStyleDeclaration::getLayeredShorthandValue): | |
+ | |
+2010-11-03 Simon Fraser <simon.fraser@apple.com> | |
+ | |
+ Reviewed by John Sullivan. | |
+ | |
+ Crash when setting context font to bad value | |
+ https://bugs.webkit.org/show_bug.cgi?id=48948 | |
+ | |
+ Null-check the CSSValue passed to CSSStyleSelector::applyPropertyToStyle(), | |
+ since it may be null if the style declaration does not contain a value | |
+ for the 'font' property. | |
+ | |
+ Test: fast/canvas/invalid-set-font-crash.html | |
+ | |
+ * css/CSSStyleSelector.cpp: | |
+ (WebCore::CSSStyleSelector::applyPropertyToStyle): | |
+ | |
+2010-10-12 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ Prevent block logical height of a root inline box from overflowing by clamping it | |
+ at INT_MAX. Otherwise, we will not be able to properly dirty the set of lines during | |
+ removal a floating object. | |
+ https://bugs.webkit.org/show_bug.cgi?id=45611 | |
+ | |
+ Test: fast/overflow/overflow-block-logical-height-crash.html | |
+ | |
+ * rendering/RootInlineBox.cpp: | |
+ (WebCore::RootInlineBox::alignBoxesInBlockDirection): | |
+ | |
+2010-10-12 Roland Steiner <rolandsteiner@chromium.org> | |
+ | |
+ Reviewed by David Hyatt. | |
+ | |
+ Bug 41040 - :before/:after content should not become part of a ruby base | |
+ https://bugs.webkit.org/show_bug.cgi?id=41040 | |
+ | |
+ Also related to: | |
+ https://bugs.webkit.org/show_bug.cgi?id=40895. | |
+ https://bugs.webkit.org/show_bug.cgi?id=43722. | |
+ | |
+ Explicitly handle :before and :after content in the default way. | |
+ | |
+ Test: fast/ruby/ruby-beforeafter.html | |
+ fast/ruby/after-doesnt-crash.html | |
+ | |
+ * rendering/RenderObject.h: | |
+ (WebCore::RenderObject::isBeforeContent): | |
+ * rendering/RenderRuby.cpp: | |
+ (WebCore::lastRubyRun): | |
+ (WebCore::RenderRubyAsInline::addChild): | |
+ (WebCore::RenderRubyAsInline::removeChild): | |
+ (WebCore::RenderRubyAsBlock::addChild): | |
+ (WebCore::RenderRubyAsBlock::removeChild): | |
+ | |
+2010-10-06 Daniel Bates <dbates@rim.com> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ ASSERTION FAILURE: Attempt to cast RenderObject to RenderFrameSet | |
+ when <frameset> has CSS content property | |
+ https://bugs.webkit.org/show_bug.cgi?id=47314 | |
+ | |
+ Fixes an issue where sending a mouse event to an HTML Frameset Element that | |
+ whose content was replaced via the CSS content property causes an assertion | |
+ failure. | |
+ | |
+ By default, HTMLFrameSetElement forwards mouse events to RenderFrameSet so as | |
+ to support resizing a frame within the set. When a <frameset> specifies an | |
+ image in its CSS content property we create a generic render object (RenderObject) | |
+ for the frame set instead of a RenderFrameSet object. The event handler code | |
+ in HTMLFrameSetElement calls WebCore::toRenderFrameSet() to cast its renderer | |
+ to type RenderFrameSet, which fails. To correct this, HTMLFrameSetElement | |
+ must check that its renderer is of type RenderFrameSet before casting to this type. | |
+ | |
+ Test: fast/frames/crash-frameset-CSS-content-property.html | |
+ | |
+ * html/HTMLFrameSetElement.cpp: | |
+ (WebCore::HTMLFrameSetElement::defaultEventHandler): Check that our renderer is | |
+ of type RenderFrameSet before casting it as such. | |
+ | |
+2010-09-30 Cris Neckar <cdn@chromium.org> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ Added check to test for removed counter node when calling findPlaceForCounter() in updateCounters(). | |
+ Added refcounting to counternodes in countermaps. | |
+ https://bugs.webkit.org/show_bug.cgi?id=46387 | |
+ | |
+ Test: fast/css/counters/counter-traverse-table-cell.html | |
+ | |
+ * rendering/CounterNode.cpp: | |
+ (WebCore::CounterNode::create): | |
+ * rendering/CounterNode.h: | |
+ * rendering/RenderCounter.cpp: | |
+ (WebCore::makeCounterNode): | |
+ (WebCore::destroyCounterNodeWithoutMapRemoval): | |
+ (WebCore::RenderCounter::destroyCounterNodes): | |
+ (WebCore::RenderCounter::destroyCounterNode): | |
+ (WebCore::updateCounters): | |
+ | |
+2010-09-30 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Reviewed by Dan Bernstein. | |
+ | |
+ While updating :before and :after content, make sure that the generated | |
+ container is allowed to add the child type. | |
+ https://bugs.webkit.org/show_bug.cgi?id=46106 | |
+ | |
+ Test: fast/css-generated-content/text-before-table-col-crash.html | |
+ | |
+ * rendering/RenderObjectChildList.cpp: | |
+ (WebCore::RenderObjectChildList::updateBeforeAfterContent): | |
+ | |
+2010-09-28 Andreas Kling <andreas.kling@nokia.com> | |
+ | |
+ Reviewed by Kenneth Rohde Christiansen. | |
+ | |
+ Canvas: Crash when setting a font with size in 'ex' units | |
+ https://bugs.webkit.org/show_bug.cgi?id=46538 | |
+ | |
+ update() the style's font after setting the style's font description. | |
+ Needed because CSSPrimitiveValue::computeLengthDouble() later assumes | |
+ that the style's font is properly initialized (for xHeight().) | |
+ | |
+ Fixes crash on IE test center's canvas-text-font-002 test. | |
+ | |
+ * html/canvas/CanvasRenderingContext2D.cpp: | |
+ (WebCore::CanvasRenderingContext2D::setFont): | |
+ | |
+2010-09-27 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Reviewed by Dan Bernstein. | |
+ | |
+ When the block RunIn is destroyed, its line box tree is not deleted. As a result, it | |
+ gets later used during dirtying of inline text boxes step where this deleted parent is | |
+ accessed. The fix is to delete the line box tree before destroying the runin block. | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=46376 | |
+ | |
+ Test: fast/text/dirty-inline-textbox-crash.html | |
+ | |
+ * rendering/RenderText.cpp: | |
+ (WebCore::RenderText::dirtyLineBoxes): | |
+ | |
+2010-09-27 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Reviewed by Dave Hyatt. | |
+ | |
+ Fix memory safety issue during positioning list marker as a result of assuming | |
+ that list item's parent can always be casted to a RenderBox. The display of the parent | |
+ can be manipluated using css as Inline which causes a bad cast. | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=46384 | |
+ | |
+ Test: fast/lists/parent-box-not-box-crash.html | |
+ | |
+ * rendering/RenderListItem.cpp: | |
+ (WebCore::RenderListItem::positionListMarker): | |
+ * rendering/RenderListMarker.cpp: | |
+ (WebCore::RenderListMarker::layout): | |
+ | |
+2010-09-23 Alexey Proskuryakov <ap@apple.com> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=46326 | |
+ Crash when trying to create a NodeIterator rooted at a document-less DocumentType node | |
+ | |
+ Test: fast/dom/node-iterator-with-doctype-root.html | |
+ | |
+ * dom/Document.cpp: (WebCore::Document::detachNodeIterator): Added a comment explaining that | |
+ attach/detach may not always be paired. | |
+ | |
+ * dom/NodeIterator.cpp: | |
+ (WebCore::NodeIterator::NodeIterator): Don't try to register with the document if there is none. | |
+ (WebCore::NodeIterator::~NodeIterator): Ditto. | |
+ (WebCore::NodeIterator::detach): Ditto. | |
+ (WebCore::NodeIterator::updateForNodeRemoval): There should be a document if we're getting a | |
+ notification. | |
+ | |
+2010-09-22 Alexey Proskuryakov <ap@apple.com> | |
+ | |
+ Reviewed by Adam Barth. | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=46222 | |
+ <rdar://problem/8461701> Document.getElementById() malfunctions if ID was changed via Attr node modification. | |
+ | |
+ Test: fast/dom/Attr/change-id-via-attr-node-value.html | |
+ | |
+ * dom/Attr.h: | |
+ * dom/Attr.cpp: | |
+ (WebCore::Attr::setValue): Separated a version callable from WebCore from one avaiable to JS. | |
+ Attr::setValue() can be called from Element::setAttribute(), and we don't want to update | |
+ m_elementsById (or to call attributeChanged()) twice in that case. | |
+ (WebCore::Attr::childrenChanged): If Attr's node children change, id changes. | |
+ | |
+ * dom/Document.cpp: (WebCore::Document::removeElementById): Added an assertion that we are | |
+ not trying to remove something that isn't there. If we are, we probably failed to update | |
+ m_elementsById earlier. | |
+ | |
+ * dom/Element.cpp: (WebCore::Element::setAttribute): If the attribute has an Attr node, its | |
+ children should be updated to match attribute value. | |
+ | |
+2010-09-21 Dan Bernstein <mitz@apple.com> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ <rdar://problem/7729077> Extending the selection to sentence boundary after a line break may select extra character | |
+ https://bugs.webkit.org/show_bug.cgi?id=46232 | |
+ | |
+ Test: editing/selection/extend-by-sentence-002.html | |
+ | |
+ * editing/visible_units.cpp: | |
+ (WebCore::nextBoundary): The text iterator\81fs range end can be the position after | |
+ the line break, in which case the next visible is actually after the first character | |
+ of the next sentence. Instead, advance the text iterator past the newline character | |
+ and return the beginning of its range, which is guaranteed to still be before the | |
+ next sentence. | |
+ | |
+2010-09-16 Alexey Proskuryakov <ap@apple.com> | |
+ | |
+ Reviewed by Adam Barth. | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=45852 | |
+ Range::selectNode and selectNodeContents misbehave when argument is in another document | |
+ | |
+ Test: fast/dom/Range/select-node-different-document.html | |
+ | |
+ There is nothing in DOM Traversal spec that says this shouldn't work, and it does work in | |
+ Firefox. | |
+ | |
+ * dom/Range.cpp: | |
+ (WebCore::Range::setDocument): | |
+ (WebCore::Range::selectNode): | |
+ (WebCore::Range::selectNodeContents): | |
+ * dom/Range.h: | |
+ | |
+2010-09-16 Tony Gentilcore <tonyg@chromium.org> | |
+ | |
+ Reviewed by Adam Barth. | |
+ | |
+ Crash in WebCore::FrameLoader::shouldInterruptLoadForXFrameOptions | |
+ https://bugs.webkit.org/show_bug.cgi?id=45833 | |
+ | |
+ Test: fast/parser/x-frame-options-detached-document-crash.html | |
+ | |
+ * dom/Document.cpp: | |
+ (WebCore::Document::processHttpEquiv): Other branches in this method already test for a null frame. So it seems to make sense to test that here as well. | |
+ | |
+2010-09-14 Darin Adler <darin@apple.com> | |
+ | |
+ Reviewed by Geoffrey Garen. | |
+ | |
+ Hang processing href attribute containing a million slashes | |
+ https://bugs.webkit.org/show_bug.cgi?id=45767 | |
+ | |
+ Test: fast/css/visited-link-hang.html | |
+ | |
+ * platform/LinkHash.cpp: | |
+ (WebCore::findSlashDotDotSlash): Added a start position argument and | |
+ changed types to use size_t consistently instead of a mix. | |
+ (WebCore::findSlashSlash): Ditto. | |
+ (WebCore::findSlashDotSlash): Ditto. | |
+ (WebCore::squeezeOutNullCharacters): Added. | |
+ (WebCore::cleanSlashDotDotSlashes): Added. Factored out part | |
+ of cleanPath (see below). | |
+ (WebCore::mergeDoubleSlashes): Ditto. | |
+ (WebCore::cleanSlashDotSlashes): Ditto. | |
+ (WebCore::cleanPath): Changed algorithm to not remove as we go to | |
+ avoid N^2 behavior; instead replace with null characters and then | |
+ do a squeeze operation after the fact. Also moved the body of the | |
+ function out of line since we normally don't have to do any cleaning. | |
+ This whole thing should go at some point -- it's not the right | |
+ algorithm -- but this should eliminate the performance problems | |
+ without changing behavior. | |
+ | |
+2010-09-07 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ Remove redundant bounds check in originalText(). Add bounds check | |
+ to previousCharacter(). No need of start() > 0 check since m_start | |
+ is unsigned and we already do start() null check inside function. | |
+ https://bugs.webkit.org/show_bug.cgi?id=45303 | |
+ | |
+ Test: fast/text/one-letter-transform-crash.html | |
+ | |
+ * rendering/RenderTextFragment.cpp: | |
+ (WebCore::RenderTextFragment::originalText): | |
+ (WebCore::RenderTextFragment::previousCharacter): | |
+ | |
+2010-08-30 Adam Barth <abarth@webkit.org> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ WebCore::RenderBlock::addChild* NULL ptrs | |
+ https://bugs.webkit.org/show_bug.cgi?id=43722 | |
+ | |
+ Also includes some cleanup of comments and ASSERTs. | |
+ | |
+ Test: fast/ruby/before-doesnt-crash.html | |
+ | |
+ * rendering/RenderRuby.cpp: | |
+ (WebCore::RenderRubyAsInline::addChild): | |
+ | |
+2010-08-18 Adam Barth <abarth@webkit.org> | |
+ | |
+ Reviewed by Adele Peterson. | |
+ | |
+ Null dereference in DOMSelection::deleteFromDocument | |
+ https://bugs.webkit.org/show_bug.cgi?id=44153 | |
+ | |
+ deleteFromDocument checks selection->isNone() before calling | |
+ selection->selection().toNormalizedRange(), but toNormalizedRange() | |
+ notes that it needs to updateLayout(), which can make the selection | |
+ isNone() again. In that case, we crash on a NULL pointer in | |
+ deleteFromDocument. I don't know how to trigger that situation in a | |
+ test, but cross_fuzz was able to hit it, so we should fix it. | |
+ | |
+ * page/DOMSelection.cpp: | |
+ (WebCore::DOMSelection::deleteFromDocument): | |
+ | |
+2010-08-17 Dmitry Titov <dimich@chromium.org> | |
+ | |
+ Reviewed by David Levin. | |
+ | |
+ MessagePort.close() crashes if the owning context was destroyed. | |
+ https://bugs.webkit.org/show_bug.cgi?id=43140 | |
+ | |
+ Test: fast/events/message-port-context-destroyed.html | |
+ | |
+ * dom/MessagePort.cpp: | |
+ (WebCore::MessagePort::postMessage): | |
+ (WebCore::MessagePort::start): | |
+ (WebCore::MessagePort::close): | |
+ (WebCore::MessagePort::contextDestroyed): | |
+ Use isEntangled() method to gate various operations on MessagePort. This method also takes into account m_closed bit. | |
+ | |
+ * dom/ScriptExecutionContext.cpp: | |
+ (WebCore::ScriptExecutionContext::stopActiveDOMObjects): | |
+ (WebCore::ScriptExecutionContext::closeMessagePorts): | |
+ * dom/ScriptExecutionContext.h: | |
+ Add closeMessagePorts() method that closes message ports at the same moments when other ActiveDOMObjects are stopped. | |
+ | |
+2010-08-17 Eric Seidel <eric@webkit.org> | |
+ | |
+ Reviewed by Adam Barth. | |
+ | |
+ Make DocumentParser safer to use | |
+ https://bugs.webkit.org/show_bug.cgi?id=43055 | |
+ | |
+ Make DocumentParser and its subclasses RefCounted, and protect | |
+ HTMLDocumentParser during parsing. It's possible for a parser to | |
+ get deleted if certain actions (e.g., a document.write()) occur | |
+ synchronously. | |
+ | |
+ The original version of this patch was written by Nate Chapin. | |
+ | |
+ DocumentParser doesn't actually have to be fully RefCounted, since | |
+ the only two things which should ever hold a reference to it are | |
+ Document and DocumentParser itself. However using RefCounted and | |
+ RefPtr was easier/cleaner than inventing a custom ref() scheme. | |
+ | |
+ This deploys a new "detach()" method throughout the parsing | |
+ framework. detach() causes the parser to disconnect from the | |
+ document so that no further modifications will be made to the | |
+ document while any possible DocumentParser stacks are unwound. | |
+ | |
+ The irony of this patch is that the new detach() system is never | |
+ used, since Document always outlives the DocumentParser in all of | |
+ our layout tests. There is an ASSERT in ~Document() to verify | |
+ that the DocumentParser will not outlive the Document. | |
+ | |
+ However I expect that we will soon either find new test cases, or change | |
+ the architecture in such a way that DocumentParser will outlive | |
+ Document. At which point, the detach() plumbing will be crucial. | |
+ Right now detach() serves as a safe-guard against use-after-free bugs | |
+ for any case where DocumentParser does outlive the Document. | |
+ | |
+ This also fixes test cases attached to: | |
+ https://bugs.webkit.org/show_bug.cgi?id=42099 | |
+ | |
+ Tests: fast/frames/document-write-in-iframe-onload.html | |
+ fast/frames/set-parent-src-synchronously.html | |
+ fast/parser/document-close-iframe-load.html | |
+ fast/parser/document-close-nested-iframe-load.html | |
+ fast/parser/iframe-sets-parent-to-javascript-url.html | |
+ | |
+ * dom/Document.cpp: | |
+ - Added a new detachParser() call to be used anywhere we | |
+ used to call m_parser.clear(). | |
+ There is an ASSERT in ~DocumentParser which ensures that | |
+ we get this right. | |
+ (WebCore::Document::removedLastRef): | |
+ (WebCore::Document::~Document): | |
+ (WebCore::Document::createParser): | |
+ (WebCore::Document::detachParser): | |
+ (WebCore::Document::cancelParsing): | |
+ (WebCore::Document::implicitOpen): | |
+ - removed redundant m_parser.clear() | |
+ (WebCore::Document::implicitClose): | |
+ * dom/Document.h: | |
+ * dom/DocumentParser.cpp: | |
+ (WebCore::DocumentParser::~DocumentParser): | |
+ - ASSERT that callers always call detach() before destruction. | |
+ - This ASSERT might prove too cumbersome, but for now it's useful. | |
+ (WebCore::DocumentParser::detach): | |
+ * dom/DocumentParser.h: | |
+ * dom/RawDataDocumentParser.h: | |
+ * dom/XMLDocumentParser.cpp: | |
+ (WebCore::XMLDocumentParser::finish): | |
+ - Add a FIXME explaining part of the reason why | |
+ stopParsing() and detach() are separate concepts. | |
+ * dom/XMLDocumentParser.h: | |
+ (WebCore::XMLDocumentParser::create): | |
+ * dom/XMLDocumentParserLibxml2.cpp: | |
+ (WebCore::XMLDocumentParser::parseDocumentFragment): | |
+ * dom/XMLDocumentParserQt.cpp: | |
+ (WebCore::XMLDocumentParser::parseDocumentFragment): | |
+ * html/HTMLConstructionSite.cpp: | |
+ (WebCore::HTMLConstructionSite::detach): | |
+ (WebCore::HTMLConstructionSite::dispatchDocumentElementAvailableIfNeeded): | |
+ * html/HTMLConstructionSite.h: | |
+ * html/HTMLDocument.cpp: | |
+ (WebCore::HTMLDocument::createParser): | |
+ * html/HTMLDocument.h: | |
+ * html/HTMLDocumentParser.cpp: | |
+ - We need to protect(this) before calling into any code | |
+ which might cause the parser to be destroyed. | |
+ (WebCore::HTMLDocumentParser::~HTMLDocumentParser): | |
+ (WebCore::HTMLDocumentParser::detach): | |
+ (WebCore::HTMLDocumentParser::resumeParsingAfterYield): | |
+ (WebCore::HTMLDocumentParser::pumpTokenizer): | |
+ (WebCore::HTMLDocumentParser::insert): | |
+ (WebCore::HTMLDocumentParser::append): | |
+ (WebCore::HTMLDocumentParser::end): | |
+ (WebCore::HTMLDocumentParser::finish): | |
+ (WebCore::HTMLDocumentParser::notifyFinished): | |
+ (WebCore::HTMLDocumentParser::executeScriptsWaitingForStylesheets): | |
+ (WebCore::HTMLDocumentParser::parseDocumentFragment): | |
+ * html/HTMLDocumentParser.h: | |
+ (WebCore::HTMLDocumentParser::create): | |
+ * html/HTMLScriptRunner.cpp: | |
+ (WebCore::HTMLScriptRunner::detach): | |
+ (WebCore::HTMLScriptRunner::executeParsingBlockingScript): | |
+ (WebCore::HTMLScriptRunner::executeScript): | |
+ (WebCore::HTMLScriptRunner::executeScriptsWaitingForStylesheets): | |
+ (WebCore::HTMLScriptRunner::runScript): | |
+ * html/HTMLScriptRunner.h: | |
+ * html/HTMLTreeBuilder.cpp: | |
+ (WebCore::HTMLTreeBuilder::detach): | |
+ (WebCore::HTMLTreeBuilder::passTokenToLegacyParser): | |
+ (WebCore::HTMLTreeBuilder::finished): | |
+ * html/HTMLTreeBuilder.h: | |
+ * html/HTMLViewSourceDocument.cpp: | |
+ (WebCore::HTMLViewSourceDocument::createParser): | |
+ * html/HTMLViewSourceDocument.h: | |
+ * html/HTMLViewSourceParser.cpp: | |
+ (WebCore::HTMLViewSourceParser::HTMLViewSourceParser): | |
+ * html/HTMLViewSourceParser.h: | |
+ (WebCore::HTMLViewSourceParser::create): | |
+ * loader/FTPDirectoryDocument.cpp: | |
+ (WebCore::FTPDirectoryDocumentParser::create): | |
+ (WebCore::FTPDirectoryDocument::createParser): | |
+ * loader/FTPDirectoryDocument.h: | |
+ * loader/ImageDocument.cpp: | |
+ (WebCore::ImageDocumentParser::create): | |
+ (WebCore::ImageDocumentParser::ImageDocumentParser): | |
+ (WebCore::ImageDocument::createParser): | |
+ * loader/ImageDocument.h: | |
+ * loader/MediaDocument.cpp: | |
+ (WebCore::MediaDocumentParser::create): | |
+ (WebCore::MediaDocument::createParser): | |
+ * loader/MediaDocument.h: | |
+ * loader/PluginDocument.cpp: | |
+ (WebCore::PluginDocumentParser::create): | |
+ (WebCore::PluginDocument::createParser): | |
+ * loader/PluginDocument.h: | |
+ * loader/SinkDocument.cpp: | |
+ (WebCore::SinkDocumentParser::create): | |
+ (WebCore::SinkDocument::createParser): | |
+ * loader/SinkDocument.h: | |
+ * loader/TextDocument.cpp: | |
+ (WebCore::TextDocumentParser::create): | |
+ (WebCore::TextDocument::createParser): | |
+ (WebCore::createTextDocumentParser): | |
+ * loader/TextDocument.h: | |
+ | |
+2010-08-15 Adam Barth <abarth@webkit.org> | |
+ | |
+ Reviewed by Eric Seidel. | |
+ | |
+ Don't try to replace a non-existent document after executing JavaScript URLs | |
+ https://bugs.webkit.org/show_bug.cgi?id=44024 | |
+ | |
+ Synchronous JavaScript execution is evil. Previously, the frame was | |
+ deleted after executing the JavaScript URL, so we'd get confused when | |
+ we tried to replace its document. | |
+ | |
+ Test: fast/frames/javascript-url-for-deleted-frame.html | |
+ | |
+ * bindings/ScriptControllerBase.cpp: | |
+ (WebCore::ScriptController::executeIfJavaScriptURL): | |
+ | |
+2010-08-13 Mihai Parparita <mihaip@chromium.org> | |
+ | |
+ Reviewed by Dimitri Glazkov. | |
+ | |
+ Session history should skip over JS redirects | |
+ https://bugs.webkit.org/show_bug.cgi?id=42861 | |
+ | |
+ Lock the back/forward list for location changes and form submits that | |
+ happen before the onload event fires that are not the result of user | |
+ gestures. | |
+ | |
+ Made form submission (at the ScheduledFormSubmission level) more similar | |
+ to ScheduledURLNavigation by having it call clientRedirected too, fixing | |
+ a long-standing FIXME. | |
+ | |
+ Test: fast/history/gesture-before-onload-location-href.html, | |
+ fast/history/gesture-before-onload-form-submit.html and updated | |
+ expectations for http/tests/history tests that used to fail. | |
+ | |
+ * loader/FormSubmission.cpp: | |
+ (WebCore::FormSubmission::requestURL): | |
+ (WebCore::FormSubmission::populateFrameLoadRequest): | |
+ * loader/FormSubmission.h: | |
+ * loader/RedirectScheduler.cpp: | |
+ (WebCore::ScheduledFormSubmission::ScheduledFormSubmission): | |
+ (WebCore::ScheduledFormSubmission::fire): | |
+ (WebCore::ScheduledFormSubmission::didStartTimer): | |
+ (WebCore::ScheduledFormSubmission::didStopTimer): | |
+ (WebCore::RedirectScheduler::scheduleRedirect): | |
+ (WebCore::RedirectScheduler::mustLockBackForwardList): | |
+ (WebCore::RedirectScheduler::scheduleLocationChange): | |
+ (WebCore::RedirectScheduler::scheduleFormSubmission): | |
+ * loader/RedirectScheduler.h: | |
+ | |
+2010-08-12 Justin Schuh <jschuh@chromium.org> | |
+ | |
+ Reviewed by Dumitru Daniliuc. | |
+ | |
+ Clear PluginData's page pointer on page refresh | |
+ https://bugs.webkit.org/show_bug.cgi?id=43888 | |
+ | |
+ Test: plugins/access-after-page-destroyed.html | |
+ | |
+ * page/Page.cpp: | |
+ (WebCore::Page::refreshPlugins): | |
+ | |
+2010-08-08 Adam Barth <abarth@webkit.org> | |
+ | |
+ Reviewed by Eric Seidel. | |
+ | |
+ cross_fuzz WebCore::SelectionController::isFocusedAndActive ReadAV@NULL (9e865de49b1800ec790dcc35d8ebd069) | |
+ https://bugs.webkit.org/show_bug.cgi?id=43040 | |
+ | |
+ The pointer from Document to Frame can be null. See http://webkit.org/coding/major-objects.html. | |
+ | |
+ * css/CSSStyleSelector.cpp: | |
+ (WebCore::CSSStyleSelector::SelectorChecker::checkOneSelector): | |
+ | |
+2010-06-23 Andy Estes <aestes@apple.com> | |
+ | |
+ Reviewed by Alexey Proskuryakov. | |
+ | |
+ <rdar://problem/8107855> Prevent a crash in WebCore when removing an | |
+ object element with an invalid data URL in in a listener to its | |
+ beforeload event. | |
+ https://bugs.webkit.org/show_bug.cgi?id=41054 | |
+ | |
+ Tests: fast/dom/beforeload/remove-bad-object-in-beforeload-listener.html | |
+ | |
+ * html/HTMLObjectElement.cpp: | |
+ (WebCore::HTMLObjectElement::renderFallbackContent): Exit early if the | |
+ object element is not in the document. | |
+ * rendering/RenderEmbeddedObject.cpp: | |
+ (WebCore::RenderEmbeddedObject::updateWidget): If RenderWidget::destroy() | |
+ was called during processing of onbeforeload, do not proceed with loading | |
+ the object. | |
+ | |
+2010-06-18 Abhishek Arya <inferno@chromium.org> | |
+ | |
+ Reviewed by Adam Barth. | |
+ | |
+ Convert column span from an unsigned short type to an unsigned int | |
+ type. Fixes a divide-by-zero crash arising from using a zero colspan | |
+ value coming from a narrow cast of an int to an unsigned short. | |
+ https://bugs.webkit.org/show_bug.cgi?id=40812 | |
+ | |
+ Test: fast/table/zero-colspan-crash.html | |
+ | |
+ * rendering/RenderTable.h: Change span from unsigned short to unsigned int. | |
+ * rendering/RenderTableSection.cpp: Fix a compiler warning with comparing | |
+ unsigned int with signed int. Value of an unsigned int here cannot be | |
+ greater than maximum positive value of a signed int. | |
+ (WebCore::RenderTableSection::addCell): | |
+ | |
+2010-06-17 Andy Estes <aestes@apple.com> | |
+ | |
+ Reviewed by Dan Bernstein. | |
+ | |
+ <rdar://problem/8091385> Prevent a crash in WebCore when removing a stylesheet link element in | |
+ in a listener to its beforeload event. | |
+ https://bugs.webkit.org/show_bug.cgi?id=40742 | |
+ | |
+ Postpone loading of link elements until after they have been inserted into the DOM and | |
+ attached. This prevents DOM mutations triggered by beforeload handlers from firing in the | |
+ midst of DOM insertion, which can lead to assertion failures and crashes. | |
+ | |
+ Test: fast/dom/beforeload/remove-link-in-beforeload-listener.html | |
+ | |
+ * html/HTMLLinkElement.cpp: | |
+ (WebCore::HTMLLinkElement::HTMLLinkElement): Initialize m_shouldProcessAfterAttach to false. | |
+ (WebCore::HTMLLinkElement::processCallback): Add a static callback function which calls | |
+ HTMLLinkElement::process(). | |
+ (WebCore::HTMLLinkElement::insertedIntoDocument): Instead of calling process() directly, set | |
+ m_shouldProcessAfterAttach to true to indicate that process() should be called after attach(). | |
+ (WebCore::HTMLLinkElement::removedFromDocument): Set m_shouldProcessAfterAttach to false. | |
+ (WebCore::HTMLLinkElement::attach): If m_shouldProcessAfterAttach is true, register | |
+ HTMLLinkElement::processCallback() as a post-attach callback. | |
+ * html/HTMLLinkElement.h: Add m_shouldProcessAfterAttach. | |
+ (WebCore::HTMLLinkElement::canLazyAttach): Override canLazyAttach() to return false to | |
+ indicate that a full attach should be performed. This ensures the post-attach callbacks are | |
+ fired. | |
+ | |
+2010-05-31 Tony Chang <tony@chromium.org> | |
+ | |
+ Reviewed by Dan Bernstein. | |
+ | |
+ REGRESSION (r58665): Infinite recursion in Position::getInlineBoxAndOffset() | |
+ https://bugs.webkit.org/show_bug.cgi?id=39946 | |
+ | |
+ r58665 added an infinite recursion check, but didn't take into consideration recursion between two | |
+ Positions. This adds a check for when | |
+ downstreamIgnoringEditingBoundaries(p1) == p2 and upstreamIgnoringEditingBoundaries(p2) == p1 | |
+ | |
+ Test: editing/selection/mixed-editability-12.html | |
+ | |
+ * dom/Position.cpp: | |
+ (WebCore::Position::getInlineBoxAndOffset): | |
+ | |
+2010-05-12 Yuzo Fujishima <yuzo@google.com> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ Fix Bug 35014 - Modifying UA rules from page JS crashes | |
+ Added a NULL check. | |
+ https://bugs.webkit.org/show_bug.cgi?id=35014 | |
+ | |
+ Test: fast/css/modify-ua-rules-from-javascript.html | |
+ | |
+ * css/CSSMutableStyleDeclaration.cpp: | |
+ (WebCore::CSSMutableStyleDeclaration::setNeedsStyleRecalc): | |
+ | |
+2010-05-02 Dan Bernstein <mitz@apple.com> | |
+ | |
+ Reviewed by Simon Fraser. | |
+ | |
+ Another case of <rdar://problem/7552959> REGRESSION: Infinite recursion in Position::getInlineBoxAndOffset() | |
+ https://bugs.webkit.org/show_bug.cgi?id=38445 | |
+ | |
+ Test: editing/selection/mixed-editability-11.html | |
+ | |
+ * dom/Position.cpp: | |
+ (WebCore::downstreamIgnoringEditingBoundaries): Added. Returns the furthest visually equivalent | |
+ position downstream, crossing any editability boundaries. | |
+ (WebCore::upstreamIgnoringEditingBoundaries): Similarly for upstream. | |
+ (WebCore::Position::getInlineBoxAndOffset): Changed the logic for finding an inline box for positions | |
+ whose node is a block flow. Instead of traversing the DOM, advance downstream or upstream as far as | |
+ possible, crossing any editability boudaries. Infinite recursion is avoided by advancing all the way | |
+ and checking that the new position is different from the starting position. Also replaced the specific | |
+ test for buttons with the generic and more comprehensive canHaveChildrenForEditing(). | |
+ | |
+2010-04-28 Julien Chaffraix <jchaffraix@webkit.org> | |
+ | |
+ Reviewed by Alexey Proskuryakov. | |
+ | |
+ [XHR] Cross-Origin synchronous request with credential raises NETWORK_ERR | |
+ https://bugs.webkit.org/show_bug.cgi?id=37781 | |
+ <rdar://problem/7905150> | |
+ | |
+ Tests: http/tests/xmlhttprequest/access-control-preflight-credential-async.html | |
+ http/tests/xmlhttprequest/access-control-preflight-credential-sync.html | |
+ | |
+ Rolling the patch in as I could not reproduce Qt results locally. | |
+ | |
+ * loader/DocumentThreadableLoader.cpp: | |
+ (WebCore::DocumentThreadableLoader::DocumentThreadableLoader): Now we remove the | |
+ credential from the request here to avoid forgetting to do so in the different code path. | |
+ (WebCore::DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest): Just add the | |
+ "Origin" header. | |
+ (WebCore::DocumentThreadableLoader::loadRequest): Check here the the credential have | |
+ been removed so that we don't leak them. Also tweaked a comment to make it clear that | |
+ the URL check has issue when credential is involved. | |
+ | |
+2010-04-09 Darin Adler <darin@apple.com> | |
+ | |
+ Reviewed by Maciej Stachowiak. | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=37370 | |
+ Division by 0 in RenderBoxModelObject::calculateFillTileSize | |
+ | |
+ Test: fast/backgrounds/background-fill-zero-area-crash.html | |
+ | |
+ * rendering/RenderBoxModelObject.cpp: | |
+ (WebCore::RenderBoxModelObject::calculateFillTileSize): Added checks for | |
+ zero before doing division. These come up when the area to fill is zero. | |
+ | |
+2010-04-08 Dimitri Glazkov <dglazkov@chromium.org> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ Manipulating document fragment members while adding it to tree may result in loss of tree integrity. | |
+ https://bugs.webkit.org/show_bug.cgi?id=36031 | |
+ | |
+ Changes the logic of appending/inserting document fragment to first stashing all of its children | |
+ to a vector, then processing the vector. This avoids ghastliness that would be caused by mutation | |
+ events mucking with the document fragment while it's being appended/inserted. | |
+ | |
+ Test: fast/dom/Node/fragment-mutation.html | |
+ | |
+ * dom/ContainerNode.cpp: | |
+ (WebCore::targetNodes): Added method to populate a vector of nodes (targets) to be used in | |
+ inserting/appending operation. | |
+ (WebCore::ContainerNode::insertBefore): Changed to use vector-based iteration. | |
+ (WebCore::ContainerNode::appendChild): Ditto. | |
+ * dom/Node.cpp: | |
+ (WebCore::Node::checkReplaceChild): Cleaned up comments. | |
+ (WebCore::Node::checkAddChild): Ditto. | |
+ | |
+2010-04-02 Justin Schuh <jschuh@chromium.org> | |
+ | |
+ Reviewed by Alexey Proskuryakov. | |
+ | |
+ XHR allows arbitrary XSRF across domains | |
+ https://bugs.webkit.org/show_bug.cgi?id=36843 | |
+ | |
+ Added a one-line change to prevent bypassing the XDC check on | |
+ synchronous preflighted requests. Added layout tests to cover | |
+ variations of this problem. | |
+ | |
+ Tests: http/tests/xmlhttprequest/access-control-preflight-async-header-denied.html | |
+ http/tests/xmlhttprequest/access-control-preflight-async-method-denied.html | |
+ http/tests/xmlhttprequest/access-control-preflight-sync-header-denied.html | |
+ http/tests/xmlhttprequest/access-control-preflight-sync-method-denied.html | |
+ | |
+ * loader/DocumentThreadableLoader.cpp: | |
+ (WebCore::DocumentThreadableLoader::preflightFailure): | |
+ | |
+2010-04-01 MORITA Hajime <morrita@google.com> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ WebCore::Document::updateLayoutIgnorePendingStylesheets NULL pointer | |
+ https://bugs.webkit.org/show_bug.cgi?id=31680 | |
+ Ownerless nodes leads a crash on DOMSelection APIs | |
+ https://bugs.webkit.org/show_bug.cgi?id=36800 | |
+ | |
+ Added guards nodes from foreign documents to DOMSelection APIs. | |
+ | |
+ Tests: editing/selection/DOMSelection-DocumentType.html | |
+ editing/selection/DOMSelection-crossing-document.html | |
+ | |
+ * editing/VisiblePosition.cpp: | |
+ (WebCore::VisiblePosition::canonicalPosition): | |
+ * page/DOMSelection.cpp: | |
+ (WebCore::DOMSelection::collapse): | |
+ (WebCore::DOMSelection::setBaseAndExtent): | |
+ (WebCore::DOMSelection::setPosition): | |
+ (WebCore::DOMSelection::extend): | |
+ (WebCore::DOMSelection::containsNode): | |
+ (WebCore::DOMSelection::isValidForPosition): | |
+ * page/DOMSelection.h: | |
+ | |
+2010-03-31 MORITA Hajime <morrita@google.com> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ Crash when writing into a detached TITLE element | |
+ https://bugs.webkit.org/show_bug.cgi?id=25567 | |
+ | |
+ Document::setTitle() invoked HTMLTitleElement::setText(), which | |
+ contains DOM tree modification, even when setTitle() is called | |
+ from HTMLTitleElement::childrenChanged(). Fix to skip setText() | |
+ when setTitle() is called childrenChanged() to avoid cascading | |
+ DOM mutations between Document and HTMLTitleElement. | |
+ | |
+ Test: fast/dom/title-content-write-set.html | |
+ | |
+ * dom/Document.cpp: | |
+ (WebCore::Document::setTitle): | |
+ | |
+2010-03-31 Geoffrey Garen <ggaren@apple.com> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ Crash submitting display:none textarea in a form | |
+ https://bugs.webkit.org/show_bug.cgi?id=36905 | |
+ | |
+ Test: fast/forms/textarea-submit-crash.html | |
+ | |
+ * html/HTMLTextAreaElement.cpp: | |
+ (WebCore::HTMLTextAreaElement::appendFormData): Do update layout before | |
+ asking our renderer for its text, since we can't rely on our renderer's | |
+ text if layout is needed. | |
+ | |
+ * rendering/RenderTextControl.cpp: | |
+ (WebCore::RenderTextControl::textWithHardLineBreaks): Don't update layout | |
+ while being asked for our text, since doing so may delete us, causing a crash. | |
+ | |
+2010-03-04 James Robinson <jamesr@chromium.org> | |
+ | |
+ Reviewed by Dimitri Glazkov. | |
+ | |
+ Handles setting HTMLSelectElement.length with mutation handlers present | |
+ https://bugs.webkit.org/show_bug.cgi?id=33983 | |
+ | |
+ When setting an HTMLSelectElement's length attribute, option elements have to be added or removed to the select | |
+ as appropriate. This is a little tricky with mutation events since they might add, remove, or reorder elements | |
+ while option elements are being added or deleted. | |
+ | |
+ Tests: fast/forms/select-set-length-optgroup.html | |
+ fast/forms/select-set-length-with-mutation-remove.html | |
+ fast/forms/select-set-length-with-mutation-reorder.html | |
+ fast/forms/select-set-length-with-mutation-reparent.html | |
+ fast/forms/select-set-length-with-mutation.html | |
+ fast/forms/select-set-length.html | |
+ | |
+ * html/HTMLSelectElement.cpp: | |
+ (WebCore::HTMLSelectElement::setLength): | |
+ | |
+2010-02-16 Mark Rowe <mrowe@apple.com> | |
+ | |
+ Reviewed by NOBODY (OOPS!). | |
+ | |
+ Bug 34974: Leak of ScheduledAction during layout tests | |
+ <https://bugs.webkit.org/show_bug.cgi?id=34974> | |
+ | |
+ ScheduledAction::create was returning a raw pointer which was threaded down through to an OwnPtr in DOMTimer. | |
+ If any of the code paths in between hit an error case and returned early the raw pointer would be leaked. We | |
+ can avoid this by passing it as a PassOwnPtr. This will ensure that the ScheduledAction is cleaned up should | |
+ an error case be hit. | |
+ | |
+ * bindings/js/JSDOMWindowCustom.cpp: | |
+ (WebCore::JSDOMWindow::setTimeout): Store the newly-created ScheduledAction in an OwnPtr and then hand it off | |
+ as the function argument. | |
+ (WebCore::JSDOMWindow::setInterval): Ditto. | |
+ * bindings/js/JSWorkerContextCustom.cpp: | |
+ (WebCore::JSWorkerContext::setTimeout): Ditto. | |
+ (WebCore::JSWorkerContext::setInterval): Ditto. | |
+ * bindings/js/ScheduledAction.cpp: | |
+ (WebCore::ScheduledAction::create): Return a PassOwnPtr. | |
+ * bindings/js/ScheduledAction.h: | |
+ * page/DOMTimer.cpp: | |
+ (WebCore::DOMTimer::DOMTimer): Update argument type. | |
+ (WebCore::DOMTimer::install): Ditto. | |
+ * page/DOMTimer.h: | |
+ * page/DOMWindow.cpp: | |
+ (WebCore::DOMWindow::setTimeout): Ditto. | |
+ (WebCore::DOMWindow::setInterval): Ditto. | |
+ * page/DOMWindow.h: | |
+ | |
+2010-01-26 Dan Bernstein <mitz@apple.com> | |
+ | |
+ Reviewed by Beth Dakin. | |
+ | |
+ <rdar://problem/7576663> Crash caused by anonymous list item | |
+ https://bugs.webkit.org/show_bug.cgi?id=34183 | |
+ | |
+ Test: fast/lists/anonymous-items.html | |
+ | |
+ enclosingList() and previousListItem() were DOM-based, but in order to work with anonymous | |
+ list items, they need to work with rthe render tree. | |
+ | |
+ * rendering/RenderListItem.cpp: | |
+ (WebCore::isList): Factored out. | |
+ (WebCore::enclosingList): Added this variant that takes a RenderObject. | |
+ (WebCore::previousListItem): Changed to travers the render tree. | |
+ (WebCore::RenderListItem::calcValue): Use the RenderObject version of enclosingList() | |
+ (WebCore::RenderListItem::setExplicitValue): Added an assertion. | |
+ (WebCore::RenderListItem::clearExplicitValue): Ditto. | |
+ | |
+2010-01-24 Maciej Stachowiak <mjs@apple.com> | |
+ | |
+ Reviewed by Dan Bernstein. | |
+ | |
+ Content with heavily nested residual style is so slow, it seems like a hang | |
+ https://bugs.webkit.org/show_bug.cgi?id=34059 | |
+ <rdar://problem/7292906> | |
+ | |
+ Test cast: fast/parser/residual-style-hang.html | |
+ | |
+ * html/HTMLParser.cpp: | |
+ (WebCore::HTMLParser::handleResidualStyleCloseTagAcrossBlocks): | |
+ Limit the number of iterations of the main loop to 5. | |
+ | |
+ The reason this limit is necessary is that otherwise, N misnested open tags followed | |
+ by N misnested close tags will cause O(N^2) of work due to cloning and attaching subtrees; | |
+ at a fixed limit, the cost is at worst O(N). | |
+ | |
+ The code that was in the loop originally ran exactly once - the loop was added in | |
+ r21472 to fix <https://bugs.webkit.org/show_bug.cgi?id=13603>. I have verified that | |
+ with the iteration limit, the bug is still fixed, both with the original test case | |
+ and with the layout tests tht were added. | |
+ | |
+2010-01-22 Alexey Proskuryakov <ap@apple.com> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=34008 | |
+ Assertion failure in KURL::setProtocol when running DOM Fuzzer | |
+ | |
+ Test: fast/dom/Window/invalid-protocol.html | |
+ | |
+ * bindings/js/JSLocationCustom.cpp: (WebCore::JSLocation::setProtocol): Raise an exception | |
+ if KURL::setProtocol fails. | |
+ | |
+ * html/HTMLAnchorElement.cpp: (WebCore::HTMLAnchorElement::setProtocol): Move argument | |
+ tweaking logic into KURL. This way, the ':' trick applies to both JSLocation and | |
+ HTMLAnchorElement, matching IE (but not Firefox). IE behavior is more permissive, and even | |
+ more logical in my opinion. | |
+ | |
+ * loader/FrameLoader.cpp: (WebCore::FrameLoader::iconURL): Assert that setting protocol | |
+ succeeded. | |
+ | |
+ * platform/KURL.cpp: (WebCore::KURL::setProtocol): Remove everything past ':', if present. | |
+ Return false if the protocol to set is not valid. | |
+ (WebCore::isValidProtocol): Made this work correctly for empty strings. | |
+ | |
+ * platform/KURL.h: isValidProtocol() is now static in KURL.cpp, it's only used in setProtocol(). | |
+ | |
+ * platform/KURLGoogle.cpp: | |
+ (WebCore::KURL::setProtocol): Always return true. This should hopefully prevent Chromium build | |
+ breakage, alhough tests will likely fail. | |
+ (WebCore::isValidProtocol): Removed, as this isn't used at the moment. | |
+ | |
+ * websockets/WebSocketHandshake.cpp: (WebCore::WebSocketHandshake::httpURLForAuthenticationAndCookies): | |
+ Assert that setting protocol succeeded. | |
+ | |
+2010-01-18 Alexey Proskuryakov <ap@apple.com> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ https://bugs.webkit.org/show_bug.cgi?id=33815 | |
+ Crash when using DOMTimer from a detached frame | |
+ | |
+ Test: fast/dom/Window/timer-null-script-execution-context.html | |
+ | |
+ * bindings/js/JSDOMWindowCustom.cpp: | |
+ (WebCore::JSDOMWindow::setTimeout): | |
+ (WebCore::JSDOMWindow::setInterval): | |
+ * page/DOMWindow.h: | |
+ * page/DOMWindow.idl: | |
+ Make setTimer and setInterval raise an exception. It is not specified in HTML5, but both | |
+ IE and Firefox do raise an exception in this situation, although different ones. | |
+ | |
+ * page/DOMWindow.cpp: | |
+ (WebCore::DOMWindow::setTimeout): Raise INVALID_ACCESS_ERR if script execution context is | |
+ null (meaning that the window is detached). | |
+ (WebCore::DOMWindow::setInterval): Ditto. | |
+ (WebCore::DOMWindow::clearTimeout): Silently return early if there is no script execution | |
+ context. | |
+ (WebCore::DOMWindow::clearInterval): Ditto. | |
+ Raise INVALID_ACCESS_ERR if script execution context is null (meaning . | |
+ | |
+2010-01-04 Darin Adler <darin@apple.com> | |
+ | |
+ Reviewed by Dan Bernstein. | |
+ | |
+ Reentrancy problem with selection in some edge cases. | |
+ https://bugs.webkit.org/show_bug.cgi?id=32842 | |
+ rdar://problem/7449974 | |
+ | |
+ Test: fast/forms/selection-layout-reentry-strange-case.html | |
+ | |
+ Move the selection display update process done in the | |
+ selectionLayoutChanged function into the layout timer | |
+ instead of doing it immediately when selection changes occur. | |
+ | |
+ * dom/Document.cpp: | |
+ (WebCore::Document::updateLayout): Changed this to use the | |
+ definition of needsLayout from FrameView rather than rolling | |
+ its own. | |
+ | |
+ * editing/SelectionController.cpp: | |
+ (WebCore::SelectionController::SelectionController): | |
+ Initialize m_needsDisplayUpdate to false. | |
+ (WebCore::SelectionController::setSelection): Call | |
+ the new setNeedsDisplayUpdate function instead of the old | |
+ badly named Frame::selectionLayoutChanged function. | |
+ (WebCore::SelectionController::setNeedsDisplayUpdate): | |
+ Set m_needsDisplayUpdate. If it is just becoming true, then | |
+ call FrameView::scheduleRelayout. | |
+ | |
+ * editing/SelectionController.h: Added setNeedsDisplayUpdate, | |
+ needsDisplayUpdate, and m_needsDisplayUpdate. | |
+ | |
+ * page/Frame.cpp: | |
+ (WebCore::Frame::setCaretVisible): Call setNeedsDisplayUpdate. | |
+ (WebCore::Frame::selectionLayoutChanged): Call | |
+ setNeedsDisplayUpdate to set it to false, since this is the | |
+ function that performs "selection display update". Later I want | |
+ to rename this function. Also added a global reentrancy check | |
+ since that's the easiest way I could think of to prevent infinite | |
+ recursion in the case where recomputeCaretRect ends up triggering | |
+ a layout. As a side effect, fixed theoretical problems in | |
+ TEXT_CARET builds by improving the ifdef. | |
+ (WebCore::Frame::caretBlinkTimerFired): Loosen assertions a | |
+ bit. Later we might want to decouple caret rect from caret state | |
+ a bit more and add these assertions back. | |
+ (WebCore::Frame::selectionBounds): Call Document::updateLayout. | |
+ This function is for external clients and they do not currently | |
+ do anything to make sure layout is up to date. | |
+ | |
+ * page/FrameView.cpp: | |
+ (WebCore::FrameView::needsLayout): Add a new clause, since | |
+ we need a call to layout if needsDisplayUpdate is true. | |
+ | |
+2009-10-02 Vitaly Repeshko <vitalyr@chromium.org> | |
+ | |
+ Reviewed by Dimitri Glazkov. | |
+ | |
+ [V8] Recursion guard for V8Proxy::callFunction. | |
+ Fixes http://crbug.com/23278. | |
+ https://bugs.webkit.org/show_bug.cgi?id=29974 | |
+ | |
+ Test: fast/xmlhttprequest/xmlhttprequest-recursive-sync-event.html | |
+ | |
+ * bindings/v8/V8Proxy.cpp: | |
+ (WebCore::V8Proxy::callFunction): | |
+ | |
+2009-12-23 Dan Bernstein <mitz@apple.com> | |
+ | |
+ Reviewed by Darin Adler. | |
+ | |
+ <rdar://problem/7487164> First line of text cannot be selected | |
+ https://bugs.webkit.org/show_bug.cgi?id=32749 | |
+ | |
+ Test: fast/text/remove-zero-length-run.html | |
+ | |
+ * rendering/RenderText.cpp: | |
+ (WebCore::RenderText::positionLineBox): Changed code that assumed that if a box was being | |
+ removed, it was the only box in the RenderText. Instead, correctly preserve the list of | |
+ text boxes. | |
+ (WebCore::RenderText::checkConsistency): Updated for earlier rename. | |
+ | |
2009-12-21 Anders Carlsson <andersca@apple.com> | |
Reviewed by Sam Weinig. | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/ScriptControllerBase.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/ScriptControllerBase.cpp | |
index 72c9f45..71eb971 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/ScriptControllerBase.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/ScriptControllerBase.cpp | |
@@ -59,12 +59,19 @@ bool ScriptController::executeIfJavaScriptURL(const KURL& url, bool userGesture, | |
if (!protocolIsJavaScript(url)) | |
return false; | |
- if (m_frame->page() && !m_frame->page()->javaScriptURLsAreAllowed()) | |
+ if (!m_frame->page()) | |
+ return true; | |
+ | |
+ if (!m_frame->page()->javaScriptURLsAreAllowed()) | |
return true; | |
if (m_frame->inViewSourceMode()) | |
return true; | |
+ // We need to hold onto the Frame here because executing script can | |
+ // destroy the frame. | |
+ RefPtr<Frame> protector(m_frame); | |
+ | |
const int javascriptSchemeLength = sizeof("javascript:") - 1; | |
String script = decodeURLEscapeSequences(url.string().substring(javascriptSchemeLength)); | |
@@ -72,6 +79,11 @@ bool ScriptController::executeIfJavaScriptURL(const KURL& url, bool userGesture, | |
if (xssAuditor()->canEvaluateJavaScriptURL(script)) | |
result = executeScript(script, userGesture); | |
+ // If executing script caused this frame to be removed from the page, we | |
+ // don't want to try to replace its document! | |
+ if (!m_frame->page()) | |
+ return true; | |
+ | |
String scriptResult; | |
#if USE(JSC) | |
JSDOMWindowShell* shell = windowShell(mainThreadNormalWorld()); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/JSCSSRuleCustom.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/JSCSSRuleCustom.cpp | |
index b0adf15..ec4fe9e 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/JSCSSRuleCustom.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/JSCSSRuleCustom.cpp | |
@@ -49,6 +49,17 @@ using namespace JSC; | |
namespace WebCore { | |
+void JSCSSRule::markChildren(MarkStack& markStack) | |
+{ | |
+ Base::markChildren(markStack); | |
+ | |
+ if (CSSStyleSheet* parentStyleSheet = impl()->parentStyleSheet()) | |
+ markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), parentStyleSheet); | |
+ | |
+ if (CSSRule* parentRule = impl()->parentRule()) | |
+ markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), parentRule); | |
+} | |
+ | |
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, CSSRule* rule) | |
{ | |
if (!rule) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp | |
index 5b90fac..5297340 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp | |
@@ -929,20 +929,30 @@ JSValue JSDOMWindow::postMessage(ExecState* exec, const ArgList& args) | |
JSValue JSDOMWindow::setTimeout(ExecState* exec, const ArgList& args) | |
{ | |
- ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec)); | |
+ OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, args, currentWorld(exec)); | |
if (exec->hadException()) | |
return jsUndefined(); | |
int delay = args.at(1).toInt32(exec); | |
- return jsNumber(exec, impl()->setTimeout(action, delay)); | |
+ | |
+ ExceptionCode ec = 0; | |
+ int result = impl()->setTimeout(action.release(), delay, ec); | |
+ setDOMException(exec, ec); | |
+ | |
+ return jsNumber(exec, result); | |
} | |
JSValue JSDOMWindow::setInterval(ExecState* exec, const ArgList& args) | |
{ | |
- ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec)); | |
+ OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, args, currentWorld(exec)); | |
if (exec->hadException()) | |
return jsUndefined(); | |
int delay = args.at(1).toInt32(exec); | |
- return jsNumber(exec, impl()->setInterval(action, delay)); | |
+ | |
+ ExceptionCode ec = 0; | |
+ int result = impl()->setInterval(action.release(), delay, ec); | |
+ setDOMException(exec, ec); | |
+ | |
+ return jsNumber(exec, result); | |
} | |
JSValue JSDOMWindow::atob(ExecState* exec, const ArgList& args) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/JSDocumentCustom.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/JSDocumentCustom.cpp | |
index 9366399..8b09cd1 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/JSDocumentCustom.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/JSDocumentCustom.cpp | |
@@ -60,16 +60,16 @@ void JSDocument::markChildren(MarkStack& markStack) | |
JSValue JSDocument::location(ExecState* exec) const | |
{ | |
- Frame* frame = static_cast<Document*>(impl())->frame(); | |
+ RefPtr<Frame> frame = impl()->frame(); | |
if (!frame) | |
return jsNull(); | |
- Location* location = frame->domWindow()->location(); | |
- if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, location)) | |
+ RefPtr<Location> location = frame->domWindow()->location(); | |
+ if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, location.get())) | |
return wrapper; | |
- JSLocation* jsLocation = new (exec) JSLocation(getDOMStructure<JSLocation>(exec, globalObject()), globalObject(), location); | |
- cacheDOMObjectWrapper(exec, location, jsLocation); | |
+ JSLocation* jsLocation = new (exec) JSLocation(getDOMStructure<JSLocation>(exec, globalObject()), globalObject(), location.get()); | |
+ cacheDOMObjectWrapper(exec, location.get(), jsLocation); | |
return jsLocation; | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/JSEventListener.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/JSEventListener.cpp | |
index ad4624d..4f255d1 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/JSEventListener.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/JSEventListener.cpp | |
@@ -82,6 +82,9 @@ void JSEventListener::invalidateJSFunction(JSC::JSObject* wrapper) | |
void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event) | |
{ | |
+#if PLATFORM(WKC) | |
+ CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT*2); | |
+#endif | |
ASSERT(scriptExecutionContext); | |
if (!scriptExecutionContext) | |
return; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/JSLocationCustom.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/JSLocationCustom.cpp | |
index 6c8e032..802adef 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/JSLocationCustom.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/JSLocationCustom.cpp | |
@@ -24,6 +24,7 @@ | |
#include "JSLocationCustom.h" | |
#include "DOMWindow.h" | |
+#include "ExceptionCode.h" | |
#include "Frame.h" | |
#include "FrameLoader.h" | |
#include "JSDOMBinding.h" | |
@@ -214,7 +215,10 @@ void JSLocation::setProtocol(ExecState* exec, JSValue value) | |
ASSERT(frame); | |
KURL url = frame->loader()->url(); | |
- url.setProtocol(value.toString(exec)); | |
+ if (!url.setProtocol(value.toString(exec))) { | |
+ setDOMException(exec, SYNTAX_ERR); | |
+ return; | |
+ } | |
navigateIfAllowed(exec, frame, url, !frame->script()->anyPageIsProcessingUserGesture(), false); | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/ScheduledAction.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/ScheduledAction.cpp | |
index 3223e53..d24e55a 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/ScheduledAction.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/ScheduledAction.cpp | |
@@ -47,7 +47,7 @@ using namespace JSC; | |
namespace WebCore { | |
-ScheduledAction* ScheduledAction::create(ExecState* exec, const ArgList& args, DOMWrapperWorld* isolatedWorld) | |
+PassOwnPtr<ScheduledAction> ScheduledAction::create(ExecState* exec, const ArgList& args, DOMWrapperWorld* isolatedWorld) | |
{ | |
JSValue v = args.at(0); | |
CallData callData; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/ScheduledAction.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/ScheduledAction.h | |
index dd13ab1..2a011f4 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/bindings/js/ScheduledAction.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/bindings/js/ScheduledAction.h | |
@@ -42,7 +42,7 @@ namespace WebCore { | |
*/ | |
class ScheduledAction : public Noncopyable { | |
public: | |
- static ScheduledAction* create(JSC::ExecState*, const JSC::ArgList&, DOMWrapperWorld* isolatedWorld); | |
+ static PassOwnPtr<ScheduledAction> create(JSC::ExecState*, const JSC::ArgList&, DOMWrapperWorld* isolatedWorld); | |
void execute(ScriptExecutionContext*); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSFontFaceRule.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSFontFaceRule.cpp | |
index 75e9a36..8db46ae 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSFontFaceRule.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSFontFaceRule.cpp | |
@@ -33,6 +33,8 @@ CSSFontFaceRule::CSSFontFaceRule(CSSStyleSheet* parent) | |
CSSFontFaceRule::~CSSFontFaceRule() | |
{ | |
+ if (m_style) | |
+ m_style->setParent(0); | |
} | |
void CSSFontFaceRule::setDeclaration(PassRefPtr<CSSMutableStyleDeclaration> style) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSGradientValue.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSGradientValue.cpp | |
index 5946d7a..06a2836 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSGradientValue.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSGradientValue.cpp | |
@@ -104,7 +104,8 @@ PassRefPtr<Gradient> CSSGradientValue::createGradient(RenderObject* renderer, co | |
Image* CSSGradientValue::image(RenderObject* renderer, const IntSize& size) | |
{ | |
- ASSERT(m_clients.contains(renderer)); | |
+ if (!m_clients.contains(renderer)) | |
+ return 0; | |
// Need to look up our size. Create a string of width*height to use as a hash key. | |
Image* result = getImage(renderer, size); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSMutableStyleDeclaration.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSMutableStyleDeclaration.cpp | |
index 31c7507..8baae22 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSMutableStyleDeclaration.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSMutableStyleDeclaration.cpp | |
@@ -330,27 +330,31 @@ String CSSMutableStyleDeclaration::getLayeredShorthandValue(const int* propertie | |
// then it was written with only one value. Here we figure out which value that was so we can | |
// report back correctly. | |
if (properties[j] == CSSPropertyBackgroundRepeatX && isPropertyImplicit(properties[j])) { | |
- if (j < number - 1 && properties[j + 1] == CSSPropertyBackgroundRepeatY) { | |
+ | |
+ // BUG 49055: make sure the value was not reset in the layer check just above. | |
+ if (j < number - 1 && properties[j + 1] == CSSPropertyBackgroundRepeatY && value) { | |
RefPtr<CSSValue> yValue; | |
RefPtr<CSSValue> nextValue = values[j + 1]; | |
- if (nextValue->isValueList()) | |
- yValue = static_cast<CSSValueList*>(nextValue.get())->itemWithoutBoundsCheck(i); | |
- else | |
- yValue = nextValue; | |
+ if (nextValue) { | |
+ if (nextValue->isValueList()) | |
+ yValue = static_cast<CSSValueList*>(nextValue.get())->itemWithoutBoundsCheck(i); | |
+ else | |
+ yValue = nextValue; | |
- int xId = static_cast<CSSPrimitiveValue*>(value.get())->getIdent(); | |
- int yId = static_cast<CSSPrimitiveValue*>(yValue.get())->getIdent(); | |
- if (xId != yId) { | |
- if (xId == CSSValueRepeat && yId == CSSValueNoRepeat) { | |
- useRepeatXShorthand = true; | |
+ int xId = static_cast<CSSPrimitiveValue*>(value.get())->getIdent(); | |
+ int yId = static_cast<CSSPrimitiveValue*>(yValue.get())->getIdent(); | |
+ if (xId != yId) { | |
+ if (xId == CSSValueRepeat && yId == CSSValueNoRepeat) { | |
+ useRepeatXShorthand = true; | |
+ ++j; | |
+ } else if (xId == CSSValueNoRepeat && yId == CSSValueRepeat) { | |
+ useRepeatYShorthand = true; | |
+ continue; | |
+ } | |
+ } else { | |
+ useSingleWordShorthand = true; | |
++j; | |
- } else if (xId == CSSValueNoRepeat && yId == CSSValueRepeat) { | |
- useRepeatYShorthand = true; | |
- continue; | |
} | |
- } else { | |
- useSingleWordShorthand = true; | |
- ++j; | |
} | |
} | |
} | |
@@ -484,7 +488,8 @@ void CSSMutableStyleDeclaration::setNeedsStyleRecalc() | |
while (StyleBase* parent = root->parent()) | |
root = parent; | |
if (root->isCSSStyleSheet()) | |
- static_cast<CSSStyleSheet*>(root)->doc()->updateStyleSelector(); | |
+ if (Document* doc = static_cast<CSSStyleSheet*>(root)->doc()) | |
+ doc->updateStyleSelector(); | |
} | |
bool CSSMutableStyleDeclaration::getPropertyPriority(int propertyID) const | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSPrimitiveValue.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSPrimitiveValue.h | |
index 87ca09a..22c5eae 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSPrimitiveValue.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSPrimitiveValue.h | |
@@ -207,7 +207,7 @@ private: | |
virtual unsigned short cssValueType() const; | |
- int m_type; | |
+ signed m_type; | |
union { | |
int ident; | |
double num; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSProperty.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSProperty.h | |
index 08c71d9..02ef3e5 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSProperty.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSProperty.h | |
@@ -62,8 +62,8 @@ public: | |
friend bool operator==(const CSSProperty&, const CSSProperty&); | |
// Make sure the following fits in 4 bytes. Really. | |
- int m_id : 15; | |
- int m_shorthandID : 15; // If this property was set as part of a shorthand, gives the shorthand. | |
+ signed m_id : 15; | |
+ signed m_shorthandID : 15; // If this property was set as part of a shorthand, gives the shorthand. | |
bool m_important : 1; | |
bool m_implicit : 1; // Whether or not the property was set implicitly as the result of a shorthand. | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSRule.idl b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSRule.idl | |
index bc57e55..0f8d0f3 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSRule.idl | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSRule.idl | |
@@ -22,6 +22,7 @@ module css { | |
// Introduced in DOM Level 2: | |
interface [ | |
+ CustomMarkFunction, | |
CustomToJS, | |
GenerateConstructor, | |
Polymorphic, | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSStyleSelector.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSStyleSelector.cpp | |
index 41f997b..08258ad 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/CSSStyleSelector.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/CSSStyleSelector.cpp | |
@@ -2528,7 +2528,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme | |
break; | |
} | |
case CSSSelector::PseudoFocus: | |
- if (e && e->focused() && e->document()->frame()->selection()->isFocusedAndActive()) | |
+ if (e && e->focused() && e->document()->frame() && e->document()->frame()->selection()->isFocusedAndActive()) | |
return true; | |
break; | |
case CSSSelector::PseudoHover: { | |
@@ -3114,7 +3114,8 @@ void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue *value, RenderStyle | |
initElementAndPseudoState(0); | |
initForStyleResolve(0, style); | |
m_style = style; | |
- applyProperty(id, value); | |
+ if (value) | |
+ applyProperty(id, value); | |
} | |
void CSSStyleSelector::applyProperty(int id, CSSValue *value) | |
@@ -4670,6 +4671,11 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) | |
applyProperty(CSSPropertyFontStyle, font->style.get()); | |
applyProperty(CSSPropertyFontVariant, font->variant.get()); | |
applyProperty(CSSPropertyFontWeight, font->weight.get()); | |
+ // The previous properties can dirty our font but they don't try to read the font's | |
+ // properties back, which is safe. However if font-size is using the 'ex' unit, it will | |
+ // need query the dirtied font's x-height to get the computed size. To be safe in this | |
+ // case, let's just update the font now. | |
+ updateFont(); | |
applyProperty(CSSPropertyFontSize, font->size.get()); | |
m_lineHeightValue = font->lineHeight.get(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/StyleSheet.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/StyleSheet.cpp | |
index 88e904c..58a1f59 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/css/StyleSheet.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/css/StyleSheet.cpp | |
@@ -86,6 +86,14 @@ StyleSheet::~StyleSheet() | |
{ | |
if (m_media) | |
m_media->setParent(0); | |
+ | |
+ // For style rules outside the document, .parentStyleSheet can become null even if the style rule | |
+ // is still observable from JavaScript. This matches the behavior of .parentNode for nodes, but | |
+ // it's not ideal because it makes the CSSOM's behavior depend on the timing of garbage collection. | |
+ for (unsigned i = 0; i < length(); ++i) { | |
+ ASSERT(item(i)->parent() == this); | |
+ item(i)->setParent(0); | |
+ } | |
} | |
StyleSheet* StyleSheet::parentStyleSheet() const | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Attr.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Attr.cpp | |
index 8a0b51f..629e74f 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Attr.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Attr.cpp | |
@@ -110,13 +110,21 @@ String Attr::nodeValue() const | |
return value(); | |
} | |
-void Attr::setValue(const AtomicString& value, ExceptionCode&) | |
+void Attr::setValue(const AtomicString& value) | |
{ | |
m_ignoreChildrenChanged++; | |
removeChildren(); | |
m_attribute->setValue(value); | |
createTextChild(); | |
m_ignoreChildrenChanged--; | |
+} | |
+ | |
+void Attr::setValue(const AtomicString& value, ExceptionCode&) | |
+{ | |
+ if (m_element && m_element->isIdAttributeName(m_attribute->name())) | |
+ m_element->updateId(m_element->getIDAttribute(), value); | |
+ | |
+ setValue(value); | |
if (m_element) | |
m_element->attributeChanged(m_attribute.get()); | |
@@ -160,6 +168,9 @@ void Attr::childrenChanged(bool changedByParser, Node* beforeChange, Node* after | |
if (n->isTextNode()) | |
val += static_cast<Text *>(n)->data(); | |
} | |
+ | |
+ if (m_element && m_element->isIdAttributeName(m_attribute->name())) | |
+ m_element->updateId(m_attribute->value(), val); | |
m_attribute->setValue(val.impl()); | |
if (m_element) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Attr.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Attr.h | |
index 2e02a02..e76d2fa 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Attr.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Attr.h | |
@@ -48,6 +48,7 @@ public: | |
const AtomicString& value() const { return m_attribute->value(); } | |
void setValue(const AtomicString&, ExceptionCode&); | |
+ void setValue(const AtomicString&); | |
Attribute* attr() const { return m_attribute.get(); } | |
const QualifiedName& qualifiedName() const { return m_attribute->name(); } | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/ContainerNode.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/ContainerNode.cpp | |
index 38abdf7..8c21836 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/ContainerNode.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/ContainerNode.cpp | |
@@ -1,467 +1,521 @@ | |
-/* | |
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | |
- * (C) 1999 Antti Koivisto (koivisto@kde.org) | |
- * (C) 2001 Dirk Mueller (mueller@kde.org) | |
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | |
- * Copyright (c) 2010 ACCESS CO., LTD. All rights reserved. | |
- * | |
- * This library is free software; you can redistribute it and/or | |
- * modify it under the terms of the GNU Library General Public | |
- * License as published by the Free Software Foundation; either | |
- * version 2 of the License, or (at your option) any later version. | |
- * | |
- * This library is distributed in the hope that it will be useful, | |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
- * Library General Public License for more details. | |
- * | |
- * You should have received a copy of the GNU Library General Public License | |
- * along with this library; see the file COPYING.LIB. If not, write to | |
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
- * Boston, MA 02110-1301, USA. | |
- */ | |
- | |
-#include "config.h" | |
-#include "ContainerNode.h" | |
- | |
-#include "BeforeLoadEvent.h" | |
-#include "Cache.h" | |
-#include "ContainerNodeAlgorithms.h" | |
-#include "DeleteButtonController.h" | |
-#include "EventNames.h" | |
-#include "ExceptionCode.h" | |
-#include "FloatRect.h" | |
-#include "Frame.h" | |
-#include "FrameView.h" | |
-#include "InlineTextBox.h" | |
-#include "MutationEvent.h" | |
-#include "Page.h" | |
-#include "RenderTheme.h" | |
-#include "RootInlineBox.h" | |
-#include "loader.h" | |
-#include <wtf/CurrentTime.h> | |
- | |
-namespace WebCore { | |
- | |
-static void dispatchChildInsertionEvents(Node*); | |
-static void dispatchChildRemovalEvents(Node*); | |
- | |
-typedef Vector<std::pair<NodeCallback, RefPtr<Node> > > NodeCallbackQueue; | |
-static NodeCallbackQueue* s_postAttachCallbackQueue; | |
- | |
-static size_t s_attachDepth; | |
-static bool s_shouldReEnableMemoryCacheCallsAfterAttach; | |
- | |
-void ContainerNode::removeAllChildren() | |
-{ | |
- removeAllChildrenInContainer<Node, ContainerNode>(this); | |
-} | |
- | |
-ContainerNode::~ContainerNode() | |
-{ | |
- removeAllChildren(); | |
-} | |
- | |
-bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach) | |
-{ | |
- // Check that this node is not "floating". | |
- // If it is, it can be deleted as a side effect of sending mutation events. | |
- ASSERT(refCount() || parent()); | |
- | |
- ec = 0; | |
- | |
- // insertBefore(node, 0) is equivalent to appendChild(node) | |
- if (!refChild) | |
- return appendChild(newChild, ec, shouldLazyAttach); | |
- | |
- // Make sure adding the new child is OK. | |
- checkAddChild(newChild.get(), ec); | |
- if (ec) | |
- return false; | |
- | |
- // NOT_FOUND_ERR: Raised if refChild is not a child of this node | |
- if (refChild->parentNode() != this) { | |
- ec = NOT_FOUND_ERR; | |
- return false; | |
- } | |
- | |
- bool isFragment = newChild->nodeType() == DOCUMENT_FRAGMENT_NODE; | |
- | |
- // If newChild is a DocumentFragment with no children; there's nothing to do. | |
- // Just return true | |
- if (isFragment && !newChild->firstChild()) | |
- return true; | |
- | |
- // Now actually add the child(ren) | |
- if (refChild->previousSibling() == newChild || refChild == newChild) // nothing to do | |
- return true; | |
- | |
- RefPtr<Node> next = refChild; | |
- RefPtr<Node> refChildPreviousSibling = refChild->previousSibling(); | |
- | |
- RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild; | |
- while (child) { | |
- RefPtr<Node> nextChild = isFragment ? child->nextSibling() : 0; | |
- | |
- // If child is already present in the tree, first remove it from the old location. | |
- if (Node* oldParent = child->parentNode()) | |
- oldParent->removeChild(child.get(), ec); | |
- if (ec) | |
- return 0; | |
- | |
- // FIXME: After sending the mutation events, "this" could be destroyed. | |
- // We can prevent that by doing a "ref", but first we have to make sure | |
- // that no callers call with ref count == 0 and parent = 0 (as of this | |
- // writing, there are definitely callers who call that way). | |
- | |
- // Due to arbitrary code running in response to a DOM mutation event it's | |
- // possible that "next" is no longer a child of "this". | |
- // It's also possible that "child" has been inserted elsewhere. | |
- // In either of those cases, we'll just stop. | |
- if (next->parentNode() != this) | |
- break; | |
- if (child->parentNode()) | |
- break; | |
- | |
- ASSERT(!child->nextSibling()); | |
- ASSERT(!child->previousSibling()); | |
- | |
- // Add child before "next". | |
- forbidEventDispatch(); | |
- Node* prev = next->previousSibling(); | |
- ASSERT(m_lastChild != prev); | |
- next->setPreviousSibling(child.get()); | |
- if (prev) { | |
- ASSERT(m_firstChild != next); | |
- ASSERT(prev->nextSibling() == next); | |
- prev->setNextSibling(child.get()); | |
- } else { | |
- ASSERT(m_firstChild == next); | |
- m_firstChild = child.get(); | |
- } | |
- child->setParent(this); | |
- child->setPreviousSibling(prev); | |
- child->setNextSibling(next.get()); | |
- allowEventDispatch(); | |
- | |
- // Dispatch the mutation events. | |
- childrenChanged(false, refChildPreviousSibling.get(), next.get(), 1); | |
- dispatchChildInsertionEvents(child.get()); | |
- | |
- // Add child to the rendering tree. | |
- if (attached() && !child->attached() && child->parent() == this) { | |
- if (shouldLazyAttach) | |
- child->lazyAttach(); | |
- else | |
- child->attach(); | |
- } | |
- | |
- child = nextChild.release(); | |
- } | |
- | |
- dispatchSubtreeModifiedEvent(); | |
- return true; | |
-} | |
- | |
-bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, bool shouldLazyAttach) | |
-{ | |
- // Check that this node is not "floating". | |
- // If it is, it can be deleted as a side effect of sending mutation events. | |
- ASSERT(refCount() || parent()); | |
- | |
- ec = 0; | |
- | |
- if (oldChild == newChild) // nothing to do | |
- return true; | |
- | |
- // Make sure replacing the old child with the new is ok | |
- checkReplaceChild(newChild.get(), oldChild, ec); | |
- if (ec) | |
- return false; | |
- | |
- // NOT_FOUND_ERR: Raised if oldChild is not a child of this node. | |
- if (!oldChild || oldChild->parentNode() != this) { | |
- ec = NOT_FOUND_ERR; | |
- return false; | |
- } | |
- | |
- RefPtr<Node> prev = oldChild->previousSibling(); | |
- RefPtr<Node> next = oldChild->nextSibling(); | |
- | |
- // Remove the node we're replacing | |
- RefPtr<Node> removedChild = oldChild; | |
- removeChild(oldChild, ec); | |
- if (ec) | |
- return false; | |
- | |
- // FIXME: After sending the mutation events, "this" could be destroyed. | |
- // We can prevent that by doing a "ref", but first we have to make sure | |
- // that no callers call with ref count == 0 and parent = 0 (as of this | |
- // writing, there are definitely callers who call that way). | |
- | |
- bool isFragment = newChild->nodeType() == DOCUMENT_FRAGMENT_NODE; | |
- | |
- // Add the new child(ren) | |
- int childCountDelta = 0; | |
- RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild; | |
- while (child) { | |
- // If the new child is already in the right place, we're done. | |
- if (prev && (prev == child || prev == child->previousSibling())) | |
- break; | |
- | |
- // For a fragment we have more children to do. | |
- RefPtr<Node> nextChild = isFragment ? child->nextSibling() : 0; | |
- | |
- // Remove child from its old position. | |
- if (Node* oldParent = child->parentNode()) | |
- oldParent->removeChild(child.get(), ec); | |
- if (ec) | |
- return false; | |
- | |
- // Due to arbitrary code running in response to a DOM mutation event it's | |
- // possible that "prev" is no longer a child of "this". | |
- // It's also possible that "child" has been inserted elsewhere. | |
- // In either of those cases, we'll just stop. | |
- if (prev && prev->parentNode() != this) | |
- break; | |
- if (child->parentNode()) | |
- break; | |
- | |
- childCountDelta++; | |
- | |
- ASSERT(!child->nextSibling()); | |
- ASSERT(!child->previousSibling()); | |
- | |
- // Add child after "prev". | |
- forbidEventDispatch(); | |
- Node* next; | |
- if (prev) { | |
- next = prev->nextSibling(); | |
- ASSERT(m_firstChild != next); | |
- prev->setNextSibling(child.get()); | |
- } else { | |
- next = m_firstChild; | |
- m_firstChild = child.get(); | |
- } | |
- if (next) { | |
- ASSERT(m_lastChild != prev); | |
- ASSERT(next->previousSibling() == prev); | |
- next->setPreviousSibling(child.get()); | |
- } else { | |
- ASSERT(m_lastChild == prev); | |
- m_lastChild = child.get(); | |
- } | |
- child->setParent(this); | |
- child->setPreviousSibling(prev.get()); | |
- child->setNextSibling(next); | |
- allowEventDispatch(); | |
- | |
- // Dispatch the mutation events | |
- dispatchChildInsertionEvents(child.get()); | |
- | |
- // Add child to the rendering tree | |
- if (attached() && !child->attached() && child->parent() == this) { | |
- if (shouldLazyAttach) | |
- child->lazyAttach(); | |
- else | |
- child->attach(); | |
- } | |
- | |
- prev = child; | |
- child = nextChild.release(); | |
- } | |
- | |
- if (childCountDelta) | |
- childrenChanged(false, prev.get(), next.get(), childCountDelta); | |
- dispatchSubtreeModifiedEvent(); | |
- return true; | |
-} | |
- | |
-void ContainerNode::willRemove() | |
-{ | |
- for (Node *n = m_firstChild; n != 0; n = n->nextSibling()) | |
- n->willRemove(); | |
- Node::willRemove(); | |
-} | |
- | |
-static ExceptionCode willRemoveChild(Node *child) | |
-{ | |
- ExceptionCode ec = 0; | |
- | |
- // fire removed from document mutation events. | |
- dispatchChildRemovalEvents(child); | |
- if (ec) | |
- return ec; | |
- | |
- if (child->attached()) | |
- child->willRemove(); | |
- | |
- return 0; | |
-} | |
- | |
-bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec) | |
-{ | |
- // Check that this node is not "floating". | |
- // If it is, it can be deleted as a side effect of sending mutation events. | |
- ASSERT(refCount() || parent()); | |
- | |
- ec = 0; | |
- | |
- // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. | |
- if (isReadOnlyNode()) { | |
- ec = NO_MODIFICATION_ALLOWED_ERR; | |
- return false; | |
- } | |
- | |
- // NOT_FOUND_ERR: Raised if oldChild is not a child of this node. | |
- if (!oldChild || oldChild->parentNode() != this) { | |
- ec = NOT_FOUND_ERR; | |
- return false; | |
- } | |
- | |
- RefPtr<Node> child = oldChild; | |
- | |
- ec = willRemoveChild(child.get()); | |
- if (ec) | |
- return false; | |
- | |
- // Mutation events might have moved this child into a different parent. | |
- if (child->parentNode() != this) { | |
- ec = NOT_FOUND_ERR; | |
- return false; | |
- } | |
- | |
- document()->removeFocusedNodeOfSubtree(child.get()); | |
- | |
-#if 1 | |
- // added at webkit.org trunk r55783 | |
+/* | |
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | |
+ * (C) 1999 Antti Koivisto (koivisto@kde.org) | |
+ * (C) 2001 Dirk Mueller (mueller@kde.org) | |
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | |
+ * Copyright (c) 2010 ACCESS CO., LTD. All rights reserved. | |
+ * | |
+ * This library is free software; you can redistribute it and/or | |
+ * modify it under the terms of the GNU Library General Public | |
+ * License as published by the Free Software Foundation; either | |
+ * version 2 of the License, or (at your option) any later version. | |
+ * | |
+ * This library is distributed in the hope that it will be useful, | |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
+ * Library General Public License for more details. | |
+ * | |
+ * You should have received a copy of the GNU Library General Public License | |
+ * along with this library; see the file COPYING.LIB. If not, write to | |
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
+ * Boston, MA 02110-1301, USA. | |
+ */ | |
+ | |
+#include "config.h" | |
+#include "ContainerNode.h" | |
+ | |
+#include "BeforeLoadEvent.h" | |
+#include "Cache.h" | |
+#include "ContainerNodeAlgorithms.h" | |
+#include "DeleteButtonController.h" | |
+#include "EventNames.h" | |
+#include "ExceptionCode.h" | |
+#include "FloatRect.h" | |
+#include "Frame.h" | |
+#include "FrameView.h" | |
+#include "InlineTextBox.h" | |
+#include "MutationEvent.h" | |
+#include "Page.h" | |
+#include "RenderTheme.h" | |
+#include "RootInlineBox.h" | |
+#include "loader.h" | |
+#include <wtf/CurrentTime.h> | |
+#include <wtf/Vector.h> | |
+ | |
+namespace WebCore { | |
+ | |
+static void dispatchChildInsertionEvents(Node*); | |
+static void dispatchChildRemovalEvents(Node*); | |
+ | |
+typedef Vector<std::pair<NodeCallback, RefPtr<Node> > > NodeCallbackQueue; | |
+typedef Vector<RefPtr<Node>, 1> NodeVector; | |
+static NodeCallbackQueue* s_postAttachCallbackQueue; | |
+ | |
+static size_t s_attachDepth; | |
+static bool s_shouldReEnableMemoryCacheCallsAfterAttach; | |
+ | |
+static void collectTargetNodes(Node* node, NodeVector& nodes) | |
+{ | |
+ if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) { | |
+ nodes.append(node); | |
+ return; | |
+ } | |
+ | |
+ for (Node* child = node->firstChild(); child; child = child->nextSibling()) | |
+ nodes.append(child); | |
+} | |
+ | |
+void ContainerNode::removeAllChildren() | |
+{ | |
+ removeAllChildrenInContainer<Node, ContainerNode>(this); | |
+} | |
+ | |
+ContainerNode::~ContainerNode() | |
+{ | |
+ removeAllChildren(); | |
+} | |
+ | |
+static inline bool checkAcceptChildGuaranteedNodeTypes(ContainerNode* newParent, Node* newChild, ExceptionCode& ec) | |
+{ | |
+ ASSERT(!newParent->isReadOnlyNode()); | |
+ if (newChild->contains(newParent)) { | |
+ ec = HIERARCHY_REQUEST_ERR; | |
+ return false; | |
+ } | |
+ | |
+ return true; | |
+} | |
+ | |
+bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach) | |
+{ | |
+ // Check that this node is not "floating". | |
+ // If it is, it can be deleted as a side effect of sending mutation events. | |
+ ASSERT(refCount() || parent()); | |
+ | |
+ RefPtr<Node> protect(this); | |
+ | |
+ ec = 0; | |
+ | |
+ // insertBefore(node, 0) is equivalent to appendChild(node) | |
+ if (!refChild) | |
+ return appendChild(newChild, ec, shouldLazyAttach); | |
+ | |
+ // Make sure adding the new child is OK. | |
+ checkAddChild(newChild.get(), ec); | |
+ if (ec) | |
+ return false; | |
+ | |
+ // NOT_FOUND_ERR: Raised if refChild is not a child of this node | |
+ if (refChild->parentNode() != this) { | |
+ ec = NOT_FOUND_ERR; | |
+ return false; | |
+ } | |
+ | |
+ NodeVector targets; | |
+ collectTargetNodes(newChild.get(), targets); | |
+ if (targets.isEmpty()) | |
+ return true; | |
+ | |
+ // We need this extra check because collectTargetNodes() can fire mutation events. | |
+ if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), ec)) | |
+ return false; | |
+ | |
+ // Now actually add the child(ren) | |
+ if (refChild->previousSibling() == newChild || refChild == newChild) // nothing to do | |
+ return true; | |
+ | |
+ RefPtr<Node> next = refChild; | |
+ RefPtr<Node> refChildPreviousSibling = refChild->previousSibling(); | |
+ | |
+ for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) { | |
+ Node* child = it->get(); | |
+ | |
+ // If child is already present in the tree, first remove it from the old location. | |
+ if (Node* oldParent = child->parentNode()) | |
+ oldParent->removeChild(child, ec); | |
+ if (ec) | |
+ return false; | |
+ | |
+ // We need this extra check because removeChild() can fire mutation events. | |
+ if (!checkAcceptChildGuaranteedNodeTypes(this, child, ec)) | |
+ return false; | |
+ | |
+ // FIXME: After sending the mutation events, "this" could be destroyed. | |
+ // We can prevent that by doing a "ref", but first we have to make sure | |
+ // that no callers call with ref count == 0 and parent = 0 (as of this | |
+ // writing, there are definitely callers who call that way). | |
+ | |
+ // Due to arbitrary code running in response to a DOM mutation event it's | |
+ // possible that "next" is no longer a child of "this". | |
+ // It's also possible that "child" has been inserted elsewhere. | |
+ // In either of those cases, we'll just stop. | |
+ if (next->parentNode() != this) | |
+ break; | |
+ if (child->parentNode()) | |
+ break; | |
+ | |
+ ASSERT(!child->nextSibling()); | |
+ ASSERT(!child->previousSibling()); | |
+ | |
+ // Add child before "next". | |
+ forbidEventDispatch(); | |
+ Node* prev = next->previousSibling(); | |
+ ASSERT(m_lastChild != prev); | |
+ next->setPreviousSibling(child); | |
+ if (prev) { | |
+ ASSERT(m_firstChild != next); | |
+ ASSERT(prev->nextSibling() == next); | |
+ prev->setNextSibling(child); | |
+ } else { | |
+ ASSERT(m_firstChild == next); | |
+ m_firstChild = child; | |
+ } | |
+ child->setParent(this); | |
+ child->setPreviousSibling(prev); | |
+ child->setNextSibling(next.get()); | |
+ allowEventDispatch(); | |
+ | |
+ // Dispatch the mutation events. | |
+ childrenChanged(false, refChildPreviousSibling.get(), next.get(), 1); | |
+ dispatchChildInsertionEvents(child); | |
+ | |
+ // Add child to the rendering tree. | |
+ if (attached() && !child->attached() && child->parent() == this) { | |
+ if (shouldLazyAttach) | |
+ child->lazyAttach(); | |
+ else | |
+ child->attach(); | |
+ } | |
+ } | |
+ | |
+ dispatchSubtreeModifiedEvent(); | |
+ return true; | |
+} | |
+ | |
+bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, bool shouldLazyAttach) | |
+{ | |
+ // Check that this node is not "floating". | |
+ // If it is, it can be deleted as a side effect of sending mutation events. | |
+ ASSERT(refCount() || parent()); | |
+ | |
+ RefPtr<Node> protect(this); | |
+ | |
+ ec = 0; | |
+ | |
+ if (oldChild == newChild) // nothing to do | |
+ return true; | |
+ | |
+ // Make sure replacing the old child with the new is ok | |
+ checkReplaceChild(newChild.get(), oldChild, ec); | |
+ if (ec) | |
+ return false; | |
+ | |
+ // NOT_FOUND_ERR: Raised if oldChild is not a child of this node. | |
+ if (!oldChild || oldChild->parentNode() != this) { | |
+ ec = NOT_FOUND_ERR; | |
+ return false; | |
+ } | |
+ | |
+ RefPtr<Node> prev = oldChild->previousSibling(); | |
+ RefPtr<Node> next = oldChild->nextSibling(); | |
+ | |
+ // Remove the node we're replacing | |
+ RefPtr<Node> removedChild = oldChild; | |
+ removeChild(oldChild, ec); | |
+ if (ec) | |
+ return false; | |
+ | |
+ // Does this one more time because removeChild() fires a MutationEvent. | |
+ checkReplaceChild(newChild.get(), oldChild, ec); | |
+ if (ec) | |
+ return false; | |
+ | |
+ // FIXME: After sending the mutation events, "this" could be destroyed. | |
+ // We can prevent that by doing a "ref", but first we have to make sure | |
+ // that no callers call with ref count == 0 and parent = 0 (as of this | |
+ // writing, there are definitely callers who call that way). | |
+ | |
+ bool isFragment = newChild->nodeType() == DOCUMENT_FRAGMENT_NODE; | |
+ | |
+ // Add the new child(ren) | |
+ int childCountDelta = 0; | |
+ RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild; | |
+ while (child) { | |
+ // If the new child is already in the right place, we're done. | |
+ if (prev && (prev == child || prev == child->previousSibling())) | |
+ break; | |
+ | |
+ // For a fragment we have more children to do. | |
+ RefPtr<Node> nextChild = isFragment ? child->nextSibling() : 0; | |
+ | |
+ // Remove child from its old position. | |
+ if (Node* oldParent = child->parentNode()) | |
+ oldParent->removeChild(child.get(), ec); | |
+ if (ec) | |
+ return false; | |
+ | |
+ // Does this one more time because removeChild() fires a MutationEvent. | |
+ checkReplaceChild(child.get(), oldChild, ec); | |
+ if (ec) | |
+ return false; | |
+ | |
+ // Due to arbitrary code running in response to a DOM mutation event it's | |
+ // possible that "prev" is no longer a child of "this". | |
+ // It's also possible that "child" has been inserted elsewhere. | |
+ // In either of those cases, we'll just stop. | |
+ if (prev && prev->parentNode() != this) | |
+ break; | |
+ if (child->parentNode()) | |
+ break; | |
+ | |
+ childCountDelta++; | |
+ | |
+ ASSERT(!child->nextSibling()); | |
+ ASSERT(!child->previousSibling()); | |
+ | |
+ // Add child after "prev". | |
+ forbidEventDispatch(); | |
+ Node* next; | |
+ if (prev) { | |
+ next = prev->nextSibling(); | |
+ ASSERT(m_firstChild != next); | |
+ prev->setNextSibling(child.get()); | |
+ } else { | |
+ next = m_firstChild; | |
+ m_firstChild = child.get(); | |
+ } | |
+ if (next) { | |
+ ASSERT(m_lastChild != prev); | |
+ ASSERT(next->previousSibling() == prev); | |
+ next->setPreviousSibling(child.get()); | |
+ } else { | |
+ ASSERT(m_lastChild == prev); | |
+ m_lastChild = child.get(); | |
+ } | |
+ child->setParent(this); | |
+ child->setPreviousSibling(prev.get()); | |
+ child->setNextSibling(next); | |
+ allowEventDispatch(); | |
+ | |
+ checkReplaceChild(child.get(), oldChild, ec); | |
+ if (ec) | |
+ return false; | |
+ | |
+ // Dispatch the mutation events | |
+ dispatchChildInsertionEvents(child.get()); | |
+ | |
+ // Add child to the rendering tree | |
+ if (attached() && !child->attached() && child->parent() == this) { | |
+ if (shouldLazyAttach) | |
+ child->lazyAttach(); | |
+ else | |
+ child->attach(); | |
+ } | |
+ | |
+ prev = child; | |
+ child = nextChild.release(); | |
+ } | |
+ | |
+ if (childCountDelta) | |
+ childrenChanged(false, prev.get(), next.get(), childCountDelta); | |
+ dispatchSubtreeModifiedEvent(); | |
+ return true; | |
+} | |
+ | |
+void ContainerNode::willRemove() | |
+{ | |
+ RefPtr<Node> protect(this); | |
+ | |
+ for (Node *n = m_firstChild; n != 0; n = n->nextSibling()) | |
+ n->willRemove(); | |
+ Node::willRemove(); | |
+} | |
+ | |
+static ExceptionCode willRemoveChild(Node *child) | |
+{ | |
+ ExceptionCode ec = 0; | |
+ | |
+ // fire removed from document mutation events. | |
+ dispatchChildRemovalEvents(child); | |
+ if (ec) | |
+ return ec; | |
+ | |
+ if (child->attached()) | |
+ child->willRemove(); | |
+ | |
+ return 0; | |
+} | |
+ | |
+bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec) | |
+{ | |
+ // Check that this node is not "floating". | |
+ // If it is, it can be deleted as a side effect of sending mutation events. | |
+ ASSERT(refCount() || parent()); | |
+ | |
+ RefPtr<Node> protect(this); | |
+ | |
+ ec = 0; | |
+ | |
+ // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. | |
+ if (isReadOnlyNode()) { | |
+ ec = NO_MODIFICATION_ALLOWED_ERR; | |
+ return false; | |
+ } | |
+ | |
+ // NOT_FOUND_ERR: Raised if oldChild is not a child of this node. | |
+ if (!oldChild || oldChild->parentNode() != this) { | |
+ ec = NOT_FOUND_ERR; | |
+ return false; | |
+ } | |
+ | |
+ RefPtr<Node> child = oldChild; | |
+ | |
+ ec = willRemoveChild(child.get()); | |
+ if (ec) | |
+ return false; | |
+ | |
+ // Mutation events might have moved this child into a different parent. | |
+ if (child->parentNode() != this) { | |
+ ec = NOT_FOUND_ERR; | |
+ return false; | |
+ } | |
+ | |
+ document()->removeFocusedNodeOfSubtree(child.get()); | |
+ | |
+#if 1 | |
+ // added at webkit.org trunk r55783 | |
// Events fired when blurring currently focused node might have moved this | |
// child into a different parent. | |
if (child->parentNode() != this) { | |
ec = NOT_FOUND_ERR; | |
return false; | |
- } | |
-#endif | |
- | |
- // FIXME: After sending the mutation events, "this" could be destroyed. | |
- // We can prevent that by doing a "ref", but first we have to make sure | |
- // that no callers call with ref count == 0 and parent = 0 (as of this | |
- // writing, there are definitely callers who call that way). | |
- | |
- forbidEventDispatch(); | |
- | |
- // Remove from rendering tree | |
- if (child->attached()) | |
- child->detach(); | |
- | |
- // Remove the child | |
- Node *prev, *next; | |
- prev = child->previousSibling(); | |
- next = child->nextSibling(); | |
- | |
- if (next) | |
- next->setPreviousSibling(prev); | |
- if (prev) | |
- prev->setNextSibling(next); | |
- if (m_firstChild == child) | |
- m_firstChild = next; | |
- if (m_lastChild == child) | |
- m_lastChild = prev; | |
- | |
- child->setPreviousSibling(0); | |
- child->setNextSibling(0); | |
- child->setParent(0); | |
- | |
- allowEventDispatch(); | |
- | |
- // Dispatch post-removal mutation events | |
- childrenChanged(false, prev, next, -1); | |
- dispatchSubtreeModifiedEvent(); | |
- | |
- if (child->inDocument()) | |
- child->removedFromDocument(); | |
- else | |
- child->removedFromTree(true); | |
- | |
- return child; | |
-} | |
- | |
-// this differs from other remove functions because it forcibly removes all the children, | |
-// regardless of read-only status or event exceptions, e.g. | |
-bool ContainerNode::removeChildren() | |
-{ | |
- if (!m_firstChild) | |
- return false; | |
- | |
- // The container node can be removed from event handlers. | |
- RefPtr<Node> protect(this); | |
- | |
- // Do any prep work needed before actually starting to detach | |
- // and remove... e.g. stop loading frames, fire unload events. | |
- // FIXME: Adding new children from event handlers can cause an infinite loop here. | |
- for (RefPtr<Node> n = m_firstChild; n; n = n->nextSibling()) | |
- willRemoveChild(n.get()); | |
- | |
- // exclude this node when looking for removed focusedNode since only children will be removed | |
- document()->removeFocusedNodeOfSubtree(this, true); | |
- | |
- forbidEventDispatch(); | |
-#if 1 | |
- // modified at webkit.org trunk r55462 | |
- Vector<RefPtr<Node> > removedChildren; | |
-#else | |
- int childCountDelta = 0; | |
-#endif | |
- while (RefPtr<Node> n = m_firstChild) { | |
-#if 0 | |
- // removed at webkit.org trunk r55462 | |
- childCountDelta--; | |
-#endif | |
- Node* next = n->nextSibling(); | |
- | |
- // Remove the node from the tree before calling detach or removedFromDocument (4427024, 4129744). | |
-#if 1 | |
- // added at webkit.org trunk r55462 | |
+ } | |
+#endif | |
+ | |
+ // FIXME: After sending the mutation events, "this" could be destroyed. | |
+ // We can prevent that by doing a "ref", but first we have to make sure | |
+ // that no callers call with ref count == 0 and parent = 0 (as of this | |
+ // writing, there are definitely callers who call that way). | |
+ | |
+ forbidEventDispatch(); | |
+ | |
+ // Remove from rendering tree | |
+ if (child->attached()) | |
+ child->detach(); | |
+ | |
+ // Remove the child | |
+ Node *prev, *next; | |
+ prev = child->previousSibling(); | |
+ next = child->nextSibling(); | |
+ | |
+ if (next) | |
+ next->setPreviousSibling(prev); | |
+ if (prev) | |
+ prev->setNextSibling(next); | |
+ if (m_firstChild == child) | |
+ m_firstChild = next; | |
+ if (m_lastChild == child) | |
+ m_lastChild = prev; | |
+ | |
+ child->setPreviousSibling(0); | |
+ child->setNextSibling(0); | |
+ child->setParent(0); | |
+ | |
+ allowEventDispatch(); | |
+ | |
+ // Dispatch post-removal mutation events | |
+ childrenChanged(false, prev, next, -1); | |
+ dispatchSubtreeModifiedEvent(); | |
+ | |
+ if (child->inDocument()) | |
+ child->removedFromDocument(); | |
+ else | |
+ child->removedFromTree(true); | |
+ | |
+ return child; | |
+} | |
+ | |
+// this differs from other remove functions because it forcibly removes all the children, | |
+// regardless of read-only status or event exceptions, e.g. | |
+bool ContainerNode::removeChildren() | |
+{ | |
+ if (!m_firstChild) | |
+ return false; | |
+ | |
+ // The container node can be removed from event handlers. | |
+ RefPtr<Node> protect(this); | |
+ | |
+ // Do any prep work needed before actually starting to detach | |
+ // and remove... e.g. stop loading frames, fire unload events. | |
+ NodeVector children; | |
+ for (Node* n = m_firstChild; n; n = n->nextSibling()) | |
+ children.append(n); | |
+ | |
+ for (NodeVector::const_iterator it = children.begin(); it != children.end(); ++it) { | |
+ Node* child = it->get(); | |
+ willRemoveChild(child); | |
+ } | |
+ | |
+ // exclude this node when looking for removed focusedNode since only children will be removed | |
+ document()->removeFocusedNodeOfSubtree(this, true); | |
+ | |
+ forbidEventDispatch(); | |
+#if 1 | |
+ // modified at webkit.org trunk r55462 | |
+ Vector<RefPtr<Node> > removedChildren; | |
+#else | |
+ int childCountDelta = 0; | |
+#endif | |
+ while (RefPtr<Node> n = m_firstChild) { | |
+#if 0 | |
+ // removed at webkit.org trunk r55462 | |
+ childCountDelta--; | |
+#endif | |
+ Node* next = n->nextSibling(); | |
+ | |
+ // Remove the node from the tree before calling detach or removedFromDocument (4427024, 4129744). | |
+#if 1 | |
+ // added at webkit.org trunk r55462 | |
// removeChild() does this after calling detach(). There is no explanation for | |
- // this discrepancy between removeChild() and its optimized version removeChildren(). | |
-#endif | |
- n->setPreviousSibling(0); | |
- n->setNextSibling(0); | |
- n->setParent(0); | |
- | |
- m_firstChild = next; | |
- if (n == m_lastChild) | |
- m_lastChild = 0; | |
- | |
- if (n->attached()) | |
- n->detach(); | |
- | |
-#if 1 | |
- // modified at webkit.org trunk r55462 | |
- removedChildren.append(n.release()); | |
-#else | |
- if (n->inDocument()) | |
- n->removedFromDocument(); | |
-#endif | |
- } | |
- allowEventDispatch(); | |
- | |
-#if 1 | |
- // added at webkit.org trunk r55462 | |
- size_t removedChildrenCount = removedChildren.size(); | |
-#endif | |
- | |
- // Dispatch a single post-removal mutation event denoting a modified subtree. | |
-#if 1 | |
- // modified at webkit.org trunk r55462 and r55465 | |
- childrenChanged(false, 0, 0, -static_cast<int>(removedChildrenCount)); | |
-#else | |
- childrenChanged(false, 0, 0, childCountDelta); | |
-#endif | |
- dispatchSubtreeModifiedEvent(); | |
- | |
-#if 1 | |
- // added at webkit.org trunk r55462 | |
+ // this discrepancy between removeChild() and its optimized version removeChildren(). | |
+#endif | |
+ n->setPreviousSibling(0); | |
+ n->setNextSibling(0); | |
+ n->setParent(0); | |
+ | |
+ m_firstChild = next; | |
+ if (n == m_lastChild) | |
+ m_lastChild = 0; | |
+ | |
+ if (n->attached()) | |
+ n->detach(); | |
+ | |
+#if 1 | |
+ // modified at webkit.org trunk r55462 | |
+ removedChildren.append(n.release()); | |
+#else | |
+ if (n->inDocument()) | |
+ n->removedFromDocument(); | |
+#endif | |
+ } | |
+ allowEventDispatch(); | |
+ | |
+#if 1 | |
+ // added at webkit.org trunk r55462 | |
+ size_t removedChildrenCount = removedChildren.size(); | |
+#endif | |
+ | |
+ // Dispatch a single post-removal mutation event denoting a modified subtree. | |
+#if 1 | |
+ // modified at webkit.org trunk r55462 and r55465 | |
+ childrenChanged(false, 0, 0, -static_cast<int>(removedChildrenCount)); | |
+#else | |
+ childrenChanged(false, 0, 0, childCountDelta); | |
+#endif | |
+ dispatchSubtreeModifiedEvent(); | |
+ | |
+#if 1 | |
+ // added at webkit.org trunk r55462 | |
for (size_t i = 0; i < removedChildrenCount; ++i) { | |
Node* removedChild = removedChildren[i].get(); | |
if (removedChild->inDocument()) | |
@@ -469,520 +523,529 @@ bool ContainerNode::removeChildren() | |
// removeChild() calls removedFromTree(true) if the child was not in the | |
// document. There is no explanation for this discrepancy between removeChild() | |
// and its optimized version removeChildren(). | |
- } | |
-#endif | |
- | |
- return true; | |
-} | |
- | |
-bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach) | |
-{ | |
- // Check that this node is not "floating". | |
- // If it is, it can be deleted as a side effect of sending mutation events. | |
- ASSERT(refCount() || parent()); | |
- | |
- ec = 0; | |
- | |
- // Make sure adding the new child is ok | |
- checkAddChild(newChild.get(), ec); | |
- if (ec) | |
- return 0; | |
- | |
- if (newChild == m_lastChild) // nothing to do | |
- return newChild; | |
- | |
- bool isFragment = newChild->nodeType() == DOCUMENT_FRAGMENT_NODE; | |
- | |
- // If newChild is a DocumentFragment with no children.... there's nothing to do. | |
- // Just return the document fragment | |
- if (isFragment && !newChild->firstChild()) | |
- return true; | |
- | |
- // Now actually add the child(ren) | |
- RefPtr<Node> prev = lastChild(); | |
- RefPtr<Node> child = isFragment ? newChild->firstChild() : newChild; | |
- while (child) { | |
- // For a fragment we have more children to do. | |
- RefPtr<Node> nextChild = isFragment ? child->nextSibling() : 0; | |
- | |
- // If child is already present in the tree, first remove it | |
- if (Node* oldParent = child->parentNode()) { | |
- oldParent->removeChild(child.get(), ec); | |
- if (ec) | |
- return 0; | |
- | |
- // If the child has a parent again, just stop what we're doing, because | |
- // that means someone is doing something with DOM mutation -- can't re-parent | |
- // a child that already has a parent. | |
- if (child->parentNode()) | |
- break; | |
- } | |
- | |
- // Append child to the end of the list | |
- forbidEventDispatch(); | |
- child->setParent(this); | |
- if (m_lastChild) { | |
- child->setPreviousSibling(m_lastChild); | |
- m_lastChild->setNextSibling(child.get()); | |
- } else | |
- m_firstChild = child.get(); | |
- m_lastChild = child.get(); | |
- allowEventDispatch(); | |
- | |
- // Dispatch the mutation events | |
- childrenChanged(false, prev.get(), 0, 1); | |
- dispatchChildInsertionEvents(child.get()); | |
- | |
- // Add child to the rendering tree | |
- if (attached() && !child->attached() && child->parent() == this) { | |
- if (shouldLazyAttach) | |
- child->lazyAttach(); | |
- else | |
- child->attach(); | |
- } | |
- | |
- child = nextChild.release(); | |
- } | |
- | |
- dispatchSubtreeModifiedEvent(); | |
- return true; | |
-} | |
- | |
-ContainerNode* ContainerNode::addChild(PassRefPtr<Node> newChild) | |
-{ | |
- ASSERT(newChild); | |
- // This function is only used during parsing. | |
- // It does not send any DOM mutation events. | |
- | |
- // Check for consistency with DTD, but only when parsing HTML. | |
- if (document()->isHTMLDocument() && !childAllowed(newChild.get())) | |
- return 0; | |
- | |
- forbidEventDispatch(); | |
- Node* last = m_lastChild; | |
- appendChildToContainer<Node, ContainerNode>(newChild.get(), this); | |
- allowEventDispatch(); | |
- | |
- document()->incDOMTreeVersion(); | |
- if (inDocument()) | |
- newChild->insertedIntoDocument(); | |
- childrenChanged(true, last, 0, 1); | |
- | |
- if (newChild->isElementNode()) | |
- return static_cast<ContainerNode*>(newChild.get()); | |
- return this; | |
-} | |
- | |
-void ContainerNode::suspendPostAttachCallbacks() | |
-{ | |
- if (!s_attachDepth) { | |
- ASSERT(!s_shouldReEnableMemoryCacheCallsAfterAttach); | |
- if (Page* page = document()->page()) { | |
- if (page->areMemoryCacheClientCallsEnabled()) { | |
- page->setMemoryCacheClientCallsEnabled(false); | |
- s_shouldReEnableMemoryCacheCallsAfterAttach = true; | |
- } | |
- } | |
- cache()->loader()->suspendPendingRequests(); | |
- } | |
- ++s_attachDepth; | |
-} | |
- | |
-void ContainerNode::resumePostAttachCallbacks() | |
-{ | |
- if (s_attachDepth == 1) { | |
- if (s_postAttachCallbackQueue) | |
- dispatchPostAttachCallbacks(); | |
- if (s_shouldReEnableMemoryCacheCallsAfterAttach) { | |
- s_shouldReEnableMemoryCacheCallsAfterAttach = false; | |
- if (Page* page = document()->page()) | |
- page->setMemoryCacheClientCallsEnabled(true); | |
- } | |
- cache()->loader()->resumePendingRequests(); | |
- } | |
- --s_attachDepth; | |
-} | |
- | |
-void ContainerNode::queuePostAttachCallback(NodeCallback callback, Node* node) | |
-{ | |
- if (!s_postAttachCallbackQueue) | |
- s_postAttachCallbackQueue = new NodeCallbackQueue; | |
- | |
- s_postAttachCallbackQueue->append(std::pair<NodeCallback, RefPtr<Node> >(callback, node)); | |
-} | |
- | |
-void ContainerNode::dispatchPostAttachCallbacks() | |
-{ | |
- // We recalculate size() each time through the loop because a callback | |
- // can add more callbacks to the end of the queue. | |
- for (size_t i = 0; i < s_postAttachCallbackQueue->size(); ++i) { | |
- std::pair<NodeCallback, RefPtr<Node> >& pair = (*s_postAttachCallbackQueue)[i]; | |
- NodeCallback callback = pair.first; | |
- Node* node = pair.second.get(); | |
- | |
- callback(node); | |
- } | |
- s_postAttachCallbackQueue->clear(); | |
-} | |
- | |
-void ContainerNode::attach() | |
-{ | |
- for (Node* child = m_firstChild; child; child = child->nextSibling()) | |
- child->attach(); | |
- Node::attach(); | |
-} | |
- | |
-void ContainerNode::detach() | |
-{ | |
- for (Node* child = m_firstChild; child; child = child->nextSibling()) | |
- child->detach(); | |
- setChildNeedsStyleRecalc(false); | |
- Node::detach(); | |
-} | |
- | |
-void ContainerNode::insertedIntoDocument() | |
-{ | |
- Node::insertedIntoDocument(); | |
- insertedIntoTree(false); | |
- for (Node* child = m_firstChild; child; child = child->nextSibling()) | |
- child->insertedIntoDocument(); | |
-} | |
- | |
-void ContainerNode::removedFromDocument() | |
-{ | |
- Node::removedFromDocument(); | |
- if (document()->cssTarget() == this) | |
- document()->setCSSTarget(0); | |
- setInDocument(false); | |
- removedFromTree(false); | |
- for (Node* child = m_firstChild; child; child = child->nextSibling()) | |
- child->removedFromDocument(); | |
-} | |
- | |
-void ContainerNode::insertedIntoTree(bool deep) | |
-{ | |
- if (!deep) | |
- return; | |
- for (Node* child = m_firstChild; child; child = child->nextSibling()) | |
- child->insertedIntoTree(true); | |
-} | |
- | |
-void ContainerNode::removedFromTree(bool deep) | |
-{ | |
- if (!deep) | |
- return; | |
- for (Node* child = m_firstChild; child; child = child->nextSibling()) | |
- child->removedFromTree(true); | |
-} | |
- | |
-void ContainerNode::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) | |
-{ | |
- Node::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); | |
- if (!changedByParser && childCountDelta) | |
- document()->nodeChildrenChanged(this); | |
- if (document()->hasNodeListCaches()) | |
- notifyNodeListsChildrenChanged(); | |
-} | |
- | |
-void ContainerNode::cloneChildNodes(ContainerNode *clone) | |
-{ | |
- // disable the delete button so it's elements are not serialized into the markup | |
- if (document()->frame()) | |
- document()->frame()->editor()->deleteButtonController()->disable(); | |
- ExceptionCode ec = 0; | |
- for (Node* n = firstChild(); n && !ec; n = n->nextSibling()) | |
- clone->appendChild(n->cloneNode(true), ec); | |
- if (document()->frame()) | |
- document()->frame()->editor()->deleteButtonController()->enable(); | |
-} | |
- | |
-// FIXME: This doesn't work correctly with transforms. | |
-bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const | |
-{ | |
- if (!renderer()) | |
- return false; | |
- // What is this code really trying to do? | |
- RenderObject *o = renderer(); | |
- RenderObject *p = o; | |
- | |
- if (!o->isInline() || o->isReplaced()) { | |
- point = o->localToAbsolute(); | |
- return true; | |
- } | |
- | |
- // find the next text/image child, to get a position | |
- while (o) { | |
- p = o; | |
- if (o->firstChild()) | |
- o = o->firstChild(); | |
- else if (o->nextSibling()) | |
- o = o->nextSibling(); | |
- else { | |
- RenderObject *next = 0; | |
- while (!next && o->parent()) { | |
- o = o->parent(); | |
- next = o->nextSibling(); | |
- } | |
- o = next; | |
- | |
- if (!o) | |
- break; | |
- } | |
- ASSERT(o); | |
- | |
- if (!o->isInline() || o->isReplaced()) { | |
- point = o->localToAbsolute(); | |
- return true; | |
- } | |
- | |
- if (p->node() && p->node() == this && o->isText() && !o->isBR() && !toRenderText(o)->firstTextBox()) { | |
- // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor | |
- } else if ((o->isText() && !o->isBR()) || o->isReplaced()) { | |
- point = o->container()->localToAbsolute(); | |
- if (o->isText() && toRenderText(o)->firstTextBox()) { | |
- point.move(toRenderText(o)->linesBoundingBox().x(), | |
- toRenderText(o)->firstTextBox()->root()->lineTop()); | |
- } else if (o->isBox()) { | |
- RenderBox* box = toRenderBox(o); | |
- point.move(box->x(), box->y()); | |
- } | |
- return true; | |
- } | |
- } | |
- | |
- // If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be | |
- // at the end of the document. Scroll to the bottom. FIXME: who said anything about scrolling? | |
- if (!o && document()->view()) { | |
- point = FloatPoint(0, document()->view()->contentsHeight()); | |
- return true; | |
- } | |
- return false; | |
-} | |
- | |
-// FIXME: This doesn't work correctly with transforms. | |
-bool ContainerNode::getLowerRightCorner(FloatPoint& point) const | |
-{ | |
- if (!renderer()) | |
- return false; | |
- | |
- RenderObject* o = renderer(); | |
- if (!o->isInline() || o->isReplaced()) { | |
- RenderBox* box = toRenderBox(o); | |
- point = o->localToAbsolute(); | |
- point.move(box->width(), box->height()); | |
- return true; | |
- } | |
- | |
- // find the last text/image child, to get a position | |
- while (o) { | |
- if (o->lastChild()) | |
- o = o->lastChild(); | |
- else if (o->previousSibling()) | |
- o = o->previousSibling(); | |
- else { | |
- RenderObject* prev = 0; | |
- while (!prev) { | |
- o = o->parent(); | |
- if (!o) | |
- return false; | |
- prev = o->previousSibling(); | |
- } | |
- o = prev; | |
- } | |
- ASSERT(o); | |
- if (o->isText() || o->isReplaced()) { | |
- point = o->container()->localToAbsolute(); | |
- if (o->isText()) { | |
- RenderText* text = toRenderText(o); | |
- IntRect linesBox = text->linesBoundingBox(); | |
- point.move(linesBox.x() + linesBox.width(), linesBox.y() + linesBox.height()); | |
- } else { | |
- RenderBox* box = toRenderBox(o); | |
- point.move(box->x() + box->width(), box->y() + box->height()); | |
- } | |
- return true; | |
- } | |
- } | |
- return true; | |
-} | |
- | |
-IntRect ContainerNode::getRect() const | |
-{ | |
- FloatPoint upperLeft, lowerRight; | |
- bool foundUpperLeft = getUpperLeftCorner(upperLeft); | |
- bool foundLowerRight = getLowerRightCorner(lowerRight); | |
- | |
- // If we've found one corner, but not the other, | |
- // then we should just return a point at the corner that we did find. | |
- if (foundUpperLeft != foundLowerRight) { | |
- if (foundUpperLeft) | |
- lowerRight = upperLeft; | |
- else | |
- upperLeft = lowerRight; | |
- } | |
- | |
- lowerRight.setX(max(upperLeft.x(), lowerRight.x())); | |
- lowerRight.setY(max(upperLeft.y(), lowerRight.y())); | |
- | |
- return enclosingIntRect(FloatRect(upperLeft, lowerRight - upperLeft)); | |
-} | |
- | |
-void ContainerNode::setFocus(bool received) | |
-{ | |
- if (focused() == received) | |
- return; | |
- | |
- Node::setFocus(received); | |
- | |
- // note that we need to recalc the style | |
- setNeedsStyleRecalc(); | |
-} | |
- | |
-void ContainerNode::setActive(bool down, bool pause) | |
-{ | |
- if (down == active()) return; | |
- | |
- Node::setActive(down); | |
- | |
- // note that we need to recalc the style | |
- // FIXME: Move to Element | |
- if (renderer()) { | |
- bool reactsToPress = renderer()->style()->affectedByActiveRules(); | |
- if (reactsToPress) | |
- setNeedsStyleRecalc(); | |
- if (renderer() && renderer()->style()->hasAppearance()) { | |
- if (renderer()->theme()->stateChanged(renderer(), PressedState)) | |
- reactsToPress = true; | |
- } | |
- if (reactsToPress && pause) { | |
- // The delay here is subtle. It relies on an assumption, namely that the amount of time it takes | |
- // to repaint the "down" state of the control is about the same time as it would take to repaint the | |
- // "up" state. Once you assume this, you can just delay for 100ms - that time (assuming that after you | |
- // leave this method, it will be about that long before the flush of the up state happens again). | |
-#ifdef HAVE_FUNC_USLEEP | |
- double startTime = currentTime(); | |
-#endif | |
- | |
- // Ensure there are no pending changes | |
- Document::updateStyleForAllDocuments(); | |
- // Do an immediate repaint. | |
- if (renderer()) | |
- renderer()->repaint(true); | |
- | |
- // FIXME: Find a substitute for usleep for Win32. | |
- // Better yet, come up with a way of doing this that doesn't use this sort of thing at all. | |
-#ifdef HAVE_FUNC_USLEEP | |
- // Now pause for a small amount of time (1/10th of a second from before we repainted in the pressed state) | |
- double remainingTime = 0.1 - (currentTime() - startTime); | |
- if (remainingTime > 0) | |
- usleep(static_cast<useconds_t>(remainingTime * 1000000.0)); | |
-#endif | |
- } | |
- } | |
-} | |
- | |
-void ContainerNode::setHovered(bool over) | |
-{ | |
- if (over == hovered()) return; | |
- | |
- Node::setHovered(over); | |
- | |
- // note that we need to recalc the style | |
- // FIXME: Move to Element | |
- if (renderer()) { | |
- if (renderer()->style()->affectedByHoverRules()) | |
- setNeedsStyleRecalc(); | |
- if (renderer() && renderer()->style()->hasAppearance()) | |
- renderer()->theme()->stateChanged(renderer(), HoverState); | |
- } | |
-} | |
- | |
-unsigned ContainerNode::childNodeCount() const | |
-{ | |
- unsigned count = 0; | |
- Node *n; | |
- for (n = firstChild(); n; n = n->nextSibling()) | |
- count++; | |
- return count; | |
-} | |
- | |
-Node *ContainerNode::childNode(unsigned index) const | |
-{ | |
- unsigned i; | |
- Node *n = firstChild(); | |
- for (i = 0; n != 0 && i < index; i++) | |
- n = n->nextSibling(); | |
- return n; | |
-} | |
- | |
-static void dispatchChildInsertionEvents(Node* child) | |
-{ | |
- ASSERT(!eventDispatchForbidden()); | |
- | |
- RefPtr<Node> c = child; | |
- RefPtr<Document> document = child->document(); | |
- | |
- if (c->parentNode() && c->parentNode()->inDocument()) | |
- c->insertedIntoDocument(); | |
- else | |
- c->insertedIntoTree(true); | |
- | |
- document->incDOMTreeVersion(); | |
- | |
- if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER)) | |
- c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode())); | |
- | |
- // dispatch the DOMNodeInsertedIntoDocument event to all descendants | |
- if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) { | |
- for (; c; c = c->traverseNextNode(child)) | |
- c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false)); | |
- } | |
-} | |
- | |
-static void dispatchChildRemovalEvents(Node* child) | |
-{ | |
- RefPtr<Node> c = child; | |
- RefPtr<Document> document = child->document(); | |
- | |
- // update auxiliary doc info (e.g. iterators) to note that node is being removed | |
- document->nodeWillBeRemoved(child); | |
- | |
- document->incDOMTreeVersion(); | |
- | |
- // dispatch pre-removal mutation events | |
- if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER)) | |
- c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode())); | |
- | |
- // dispatch the DOMNodeRemovedFromDocument event to all descendants | |
- if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) { | |
- for (; c; c = c->traverseNextNode(child)) | |
- c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false)); | |
- } | |
-} | |
- | |
-bool ContainerNode::dispatchBeforeLoadEvent(const String& sourceURL) | |
-{ | |
- if (!document()->hasListenerType(Document::BEFORELOAD_LISTENER)) | |
- return true; | |
- | |
- RefPtr<ContainerNode> protector(this); | |
- RefPtr<BeforeLoadEvent> beforeLoadEvent = BeforeLoadEvent::create(sourceURL); | |
- dispatchEvent(beforeLoadEvent.get()); | |
- return !beforeLoadEvent->defaultPrevented(); | |
-} | |
- | |
-#if PLATFORM(WKC) | |
-void ContainerNode::deleteSharedInstance() | |
-{ | |
- delete s_postAttachCallbackQueue; | |
-} | |
- | |
-void ContainerNode::resetVariables() | |
-{ | |
- s_postAttachCallbackQueue = 0; | |
- s_attachDepth = 0; | |
- s_shouldReEnableMemoryCacheCallsAfterAttach = false; | |
-} | |
-#endif | |
- | |
-} // namespace WebCore | |
+ } | |
+#endif | |
+ | |
+ return true; | |
+} | |
+ | |
+bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach) | |
+{ | |
+ RefPtr<ContainerNode> protect(this); | |
+ | |
+ // Check that this node is not "floating". | |
+ // If it is, it can be deleted as a side effect of sending mutation events. | |
+ ASSERT(refCount() || parent()); | |
+ | |
+ ec = 0; | |
+ | |
+ // Make sure adding the new child is ok | |
+ checkAddChild(newChild.get(), ec); | |
+ if (ec) | |
+ return false; | |
+ | |
+ if (newChild == m_lastChild) // nothing to do | |
+ return newChild; | |
+ | |
+ NodeVector targets; | |
+ collectTargetNodes(newChild.get(), targets); | |
+ if (targets.isEmpty()) | |
+ return true; | |
+ | |
+ // We need this extra check because collectTargetNodes() can fire mutation events. | |
+ if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), ec)) | |
+ return false; | |
+ | |
+ // Now actually add the child(ren) | |
+ RefPtr<Node> prev = lastChild(); | |
+ for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) { | |
+ Node* child = it->get(); | |
+ | |
+ // If child is already present in the tree, first remove it | |
+ if (Node* oldParent = child->parentNode()) { | |
+ oldParent->removeChild(child, ec); | |
+ if (ec) | |
+ return false; | |
+ | |
+ // We need this extra check because removeChild() can fire mutation events. | |
+ if (!checkAcceptChildGuaranteedNodeTypes(this, child, ec)) | |
+ return false; | |
+ | |
+ // If the child has a parent again, just stop what we're doing, because | |
+ // that means someone is doing something with DOM mutation -- can't re-parent | |
+ // a child that already has a parent. | |
+ if (child->parentNode()) | |
+ break; | |
+ } | |
+ | |
+ // Append child to the end of the list | |
+ forbidEventDispatch(); | |
+ child->setParent(this); | |
+ if (m_lastChild) { | |
+ child->setPreviousSibling(m_lastChild); | |
+ m_lastChild->setNextSibling(child); | |
+ } else | |
+ m_firstChild = child; | |
+ m_lastChild = child; | |
+ allowEventDispatch(); | |
+ | |
+ // Dispatch the mutation events | |
+ childrenChanged(false, prev.get(), 0, 1); | |
+ dispatchChildInsertionEvents(child); | |
+ | |
+ // Add child to the rendering tree | |
+ if (attached() && !child->attached() && child->parent() == this) { | |
+ if (shouldLazyAttach) | |
+ child->lazyAttach(); | |
+ else | |
+ child->attach(); | |
+ } | |
+ } | |
+ | |
+ dispatchSubtreeModifiedEvent(); | |
+ return true; | |
+} | |
+ | |
+ContainerNode* ContainerNode::addChild(PassRefPtr<Node> newChild) | |
+{ | |
+ ASSERT(newChild); | |
+ // This function is only used during parsing. | |
+ // It does not send any DOM mutation events. | |
+ | |
+ // Check for consistency with DTD, but only when parsing HTML. | |
+ if (document()->isHTMLDocument() && !childAllowed(newChild.get())) | |
+ return 0; | |
+ | |
+ forbidEventDispatch(); | |
+ Node* last = m_lastChild; | |
+ appendChildToContainer<Node, ContainerNode>(newChild.get(), this); | |
+ allowEventDispatch(); | |
+ | |
+ document()->incDOMTreeVersion(); | |
+ if (inDocument()) | |
+ newChild->insertedIntoDocument(); | |
+ childrenChanged(true, last, 0, 1); | |
+ | |
+ if (newChild->isElementNode()) | |
+ return static_cast<ContainerNode*>(newChild.get()); | |
+ return this; | |
+} | |
+ | |
+void ContainerNode::suspendPostAttachCallbacks() | |
+{ | |
+ if (!s_attachDepth) { | |
+ ASSERT(!s_shouldReEnableMemoryCacheCallsAfterAttach); | |
+ if (Page* page = document()->page()) { | |
+ if (page->areMemoryCacheClientCallsEnabled()) { | |
+ page->setMemoryCacheClientCallsEnabled(false); | |
+ s_shouldReEnableMemoryCacheCallsAfterAttach = true; | |
+ } | |
+ } | |
+ cache()->loader()->suspendPendingRequests(); | |
+ } | |
+ ++s_attachDepth; | |
+} | |
+ | |
+void ContainerNode::resumePostAttachCallbacks() | |
+{ | |
+ if (s_attachDepth == 1) { | |
+ if (s_postAttachCallbackQueue) | |
+ dispatchPostAttachCallbacks(); | |
+ if (s_shouldReEnableMemoryCacheCallsAfterAttach) { | |
+ s_shouldReEnableMemoryCacheCallsAfterAttach = false; | |
+ if (Page* page = document()->page()) | |
+ page->setMemoryCacheClientCallsEnabled(true); | |
+ } | |
+ cache()->loader()->resumePendingRequests(); | |
+ } | |
+ --s_attachDepth; | |
+} | |
+ | |
+void ContainerNode::queuePostAttachCallback(NodeCallback callback, Node* node) | |
+{ | |
+ if (!s_postAttachCallbackQueue) | |
+ s_postAttachCallbackQueue = new NodeCallbackQueue; | |
+ | |
+ s_postAttachCallbackQueue->append(std::pair<NodeCallback, RefPtr<Node> >(callback, node)); | |
+} | |
+ | |
+void ContainerNode::dispatchPostAttachCallbacks() | |
+{ | |
+ // We recalculate size() each time through the loop because a callback | |
+ // can add more callbacks to the end of the queue. | |
+ for (size_t i = 0; i < s_postAttachCallbackQueue->size(); ++i) { | |
+ std::pair<NodeCallback, RefPtr<Node> >& pair = (*s_postAttachCallbackQueue)[i]; | |
+ NodeCallback callback = pair.first; | |
+ Node* node = pair.second.get(); | |
+ | |
+ callback(node); | |
+ } | |
+ s_postAttachCallbackQueue->clear(); | |
+} | |
+ | |
+void ContainerNode::attach() | |
+{ | |
+ for (Node* child = m_firstChild; child; child = child->nextSibling()) | |
+ child->attach(); | |
+ Node::attach(); | |
+} | |
+ | |
+void ContainerNode::detach() | |
+{ | |
+ for (Node* child = m_firstChild; child; child = child->nextSibling()) | |
+ child->detach(); | |
+ setChildNeedsStyleRecalc(false); | |
+ Node::detach(); | |
+} | |
+ | |
+void ContainerNode::insertedIntoDocument() | |
+{ | |
+ RefPtr<Node> protect(this); | |
+ | |
+ Node::insertedIntoDocument(); | |
+ insertedIntoTree(false); | |
+ for (Node* child = m_firstChild; child; child = child->nextSibling()) | |
+ child->insertedIntoDocument(); | |
+} | |
+ | |
+void ContainerNode::removedFromDocument() | |
+{ | |
+ Node::removedFromDocument(); | |
+ if (document()->cssTarget() == this) | |
+ document()->setCSSTarget(0); | |
+ setInDocument(false); | |
+ removedFromTree(false); | |
+ for (Node* child = m_firstChild; child; child = child->nextSibling()) | |
+ child->removedFromDocument(); | |
+} | |
+ | |
+void ContainerNode::insertedIntoTree(bool deep) | |
+{ | |
+#if PLATFORM(WKC) | |
+ CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); | |
+#endif | |
+ if (!deep) | |
+ return; | |
+ for (Node* child = m_firstChild; child; child = child->nextSibling()) | |
+ child->insertedIntoTree(true); | |
+} | |
+ | |
+void ContainerNode::removedFromTree(bool deep) | |
+{ | |
+ if (!deep) | |
+ return; | |
+ for (Node* child = m_firstChild; child; child = child->nextSibling()) | |
+ child->removedFromTree(true); | |
+} | |
+ | |
+void ContainerNode::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) | |
+{ | |
+ Node::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); | |
+ if (!changedByParser && childCountDelta) | |
+ document()->nodeChildrenChanged(this); | |
+ if (document()->hasNodeListCaches()) | |
+ notifyNodeListsChildrenChanged(); | |
+} | |
+ | |
+void ContainerNode::cloneChildNodes(ContainerNode *clone) | |
+{ | |
+ // disable the delete button so it's elements are not serialized into the markup | |
+ if (document()->frame()) | |
+ document()->frame()->editor()->deleteButtonController()->disable(); | |
+ ExceptionCode ec = 0; | |
+ for (Node* n = firstChild(); n && !ec; n = n->nextSibling()) | |
+ clone->appendChild(n->cloneNode(true), ec); | |
+ if (document()->frame()) | |
+ document()->frame()->editor()->deleteButtonController()->enable(); | |
+} | |
+ | |
+// FIXME: This doesn't work correctly with transforms. | |
+bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const | |
+{ | |
+ if (!renderer()) | |
+ return false; | |
+ // What is this code really trying to do? | |
+ RenderObject *o = renderer(); | |
+ RenderObject *p = o; | |
+ | |
+ if (!o->isInline() || o->isReplaced()) { | |
+ point = o->localToAbsolute(); | |
+ return true; | |
+ } | |
+ | |
+ // find the next text/image child, to get a position | |
+ while (o) { | |
+ p = o; | |
+ if (o->firstChild()) | |
+ o = o->firstChild(); | |
+ else if (o->nextSibling()) | |
+ o = o->nextSibling(); | |
+ else { | |
+ RenderObject *next = 0; | |
+ while (!next && o->parent()) { | |
+ o = o->parent(); | |
+ next = o->nextSibling(); | |
+ } | |
+ o = next; | |
+ | |
+ if (!o) | |
+ break; | |
+ } | |
+ ASSERT(o); | |
+ | |
+ if (!o->isInline() || o->isReplaced()) { | |
+ point = o->localToAbsolute(); | |
+ return true; | |
+ } | |
+ | |
+ if (p->node() && p->node() == this && o->isText() && !o->isBR() && !toRenderText(o)->firstTextBox()) { | |
+ // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor | |
+ } else if ((o->isText() && !o->isBR()) || o->isReplaced()) { | |
+ point = o->container()->localToAbsolute(); | |
+ if (o->isText() && toRenderText(o)->firstTextBox()) { | |
+ point.move(toRenderText(o)->linesBoundingBox().x(), | |
+ toRenderText(o)->firstTextBox()->root()->lineTop()); | |
+ } else if (o->isBox()) { | |
+ RenderBox* box = toRenderBox(o); | |
+ point.move(box->x(), box->y()); | |
+ } | |
+ return true; | |
+ } | |
+ } | |
+ | |
+ // If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be | |
+ // at the end of the document. Scroll to the bottom. FIXME: who said anything about scrolling? | |
+ if (!o && document()->view()) { | |
+ point = FloatPoint(0, document()->view()->contentsHeight()); | |
+ return true; | |
+ } | |
+ return false; | |
+} | |
+ | |
+// FIXME: This doesn't work correctly with transforms. | |
+bool ContainerNode::getLowerRightCorner(FloatPoint& point) const | |
+{ | |
+ if (!renderer()) | |
+ return false; | |
+ | |
+ RenderObject* o = renderer(); | |
+ if (!o->isInline() || o->isReplaced()) { | |
+ RenderBox* box = toRenderBox(o); | |
+ point = o->localToAbsolute(); | |
+ point.move(box->width(), box->height()); | |
+ return true; | |
+ } | |
+ | |
+ // find the last text/image child, to get a position | |
+ while (o) { | |
+ if (o->lastChild()) | |
+ o = o->lastChild(); | |
+ else if (o->previousSibling()) | |
+ o = o->previousSibling(); | |
+ else { | |
+ RenderObject* prev = 0; | |
+ while (!prev) { | |
+ o = o->parent(); | |
+ if (!o) | |
+ return false; | |
+ prev = o->previousSibling(); | |
+ } | |
+ o = prev; | |
+ } | |
+ ASSERT(o); | |
+ if (o->isText() || o->isReplaced()) { | |
+ point = o->container()->localToAbsolute(); | |
+ if (o->isText()) { | |
+ RenderText* text = toRenderText(o); | |
+ IntRect linesBox = text->linesBoundingBox(); | |
+ point.move(linesBox.x() + linesBox.width(), linesBox.y() + linesBox.height()); | |
+ } else { | |
+ RenderBox* box = toRenderBox(o); | |
+ point.move(box->x() + box->width(), box->y() + box->height()); | |
+ } | |
+ return true; | |
+ } | |
+ } | |
+ return true; | |
+} | |
+ | |
+IntRect ContainerNode::getRect() const | |
+{ | |
+ FloatPoint upperLeft, lowerRight; | |
+ bool foundUpperLeft = getUpperLeftCorner(upperLeft); | |
+ bool foundLowerRight = getLowerRightCorner(lowerRight); | |
+ | |
+ // If we've found one corner, but not the other, | |
+ // then we should just return a point at the corner that we did find. | |
+ if (foundUpperLeft != foundLowerRight) { | |
+ if (foundUpperLeft) | |
+ lowerRight = upperLeft; | |
+ else | |
+ upperLeft = lowerRight; | |
+ } | |
+ | |
+ lowerRight.setX(max(upperLeft.x(), lowerRight.x())); | |
+ lowerRight.setY(max(upperLeft.y(), lowerRight.y())); | |
+ | |
+ return enclosingIntRect(FloatRect(upperLeft, lowerRight - upperLeft)); | |
+} | |
+ | |
+void ContainerNode::setFocus(bool received) | |
+{ | |
+ if (focused() == received) | |
+ return; | |
+ | |
+ Node::setFocus(received); | |
+ | |
+ // note that we need to recalc the style | |
+ setNeedsStyleRecalc(); | |
+} | |
+ | |
+void ContainerNode::setActive(bool down, bool pause) | |
+{ | |
+ if (down == active()) return; | |
+ | |
+ Node::setActive(down); | |
+ | |
+ // note that we need to recalc the style | |
+ // FIXME: Move to Element | |
+ if (renderer()) { | |
+ bool reactsToPress = renderer()->style()->affectedByActiveRules(); | |
+ if (reactsToPress) | |
+ setNeedsStyleRecalc(); | |
+ if (renderer() && renderer()->style()->hasAppearance()) { | |
+ if (renderer()->theme()->stateChanged(renderer(), PressedState)) | |
+ reactsToPress = true; | |
+ } | |
+ if (reactsToPress && pause) { | |
+ // The delay here is subtle. It relies on an assumption, namely that the amount of time it takes | |
+ // to repaint the "down" state of the control is about the same time as it would take to repaint the | |
+ // "up" state. Once you assume this, you can just delay for 100ms - that time (assuming that after you | |
+ // leave this method, it will be about that long before the flush of the up state happens again). | |
+#ifdef HAVE_FUNC_USLEEP | |
+ double startTime = currentTime(); | |
+#endif | |
+ | |
+ // Ensure there are no pending changes | |
+ Document::updateStyleForAllDocuments(); | |
+ // Do an immediate repaint. | |
+ if (renderer()) | |
+ renderer()->repaint(true); | |
+ | |
+ // FIXME: Find a substitute for usleep for Win32. | |
+ // Better yet, come up with a way of doing this that doesn't use this sort of thing at all. | |
+#ifdef HAVE_FUNC_USLEEP | |
+ // Now pause for a small amount of time (1/10th of a second from before we repainted in the pressed state) | |
+ double remainingTime = 0.1 - (currentTime() - startTime); | |
+ if (remainingTime > 0) | |
+ usleep(static_cast<useconds_t>(remainingTime * 1000000.0)); | |
+#endif | |
+ } | |
+ } | |
+} | |
+ | |
+void ContainerNode::setHovered(bool over) | |
+{ | |
+ if (over == hovered()) return; | |
+ | |
+ Node::setHovered(over); | |
+ | |
+ // note that we need to recalc the style | |
+ // FIXME: Move to Element | |
+ if (renderer()) { | |
+ if (renderer()->style()->affectedByHoverRules()) | |
+ setNeedsStyleRecalc(); | |
+ if (renderer() && renderer()->style()->hasAppearance()) | |
+ renderer()->theme()->stateChanged(renderer(), HoverState); | |
+ } | |
+} | |
+ | |
+unsigned ContainerNode::childNodeCount() const | |
+{ | |
+ unsigned count = 0; | |
+ Node *n; | |
+ for (n = firstChild(); n; n = n->nextSibling()) | |
+ count++; | |
+ return count; | |
+} | |
+ | |
+Node *ContainerNode::childNode(unsigned index) const | |
+{ | |
+ unsigned i; | |
+ Node *n = firstChild(); | |
+ for (i = 0; n != 0 && i < index; i++) | |
+ n = n->nextSibling(); | |
+ return n; | |
+} | |
+ | |
+static void dispatchChildInsertionEvents(Node* child) | |
+{ | |
+ ASSERT(!eventDispatchForbidden()); | |
+ | |
+ RefPtr<Node> c = child; | |
+ RefPtr<Document> document = child->document(); | |
+ | |
+ if (c->parentNode() && c->parentNode()->inDocument()) | |
+ c->insertedIntoDocument(); | |
+ else | |
+ c->insertedIntoTree(true); | |
+ | |
+ document->incDOMTreeVersion(); | |
+ | |
+ if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER)) | |
+ c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode())); | |
+ | |
+ // dispatch the DOMNodeInsertedIntoDocument event to all descendants | |
+ if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) { | |
+ for (; c; c = c->traverseNextNode(child)) | |
+ c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false)); | |
+ } | |
+} | |
+ | |
+static void dispatchChildRemovalEvents(Node* child) | |
+{ | |
+ RefPtr<Node> c = child; | |
+ RefPtr<Document> document = child->document(); | |
+ | |
+ // update auxiliary doc info (e.g. iterators) to note that node is being removed | |
+ document->nodeWillBeRemoved(child); | |
+ | |
+ document->incDOMTreeVersion(); | |
+ | |
+ // dispatch pre-removal mutation events | |
+ if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER)) | |
+ c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode())); | |
+ | |
+ // dispatch the DOMNodeRemovedFromDocument event to all descendants | |
+ if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) { | |
+ for (; c; c = c->traverseNextNode(child)) | |
+ c->dispatchEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false)); | |
+ } | |
+} | |
+ | |
+bool ContainerNode::dispatchBeforeLoadEvent(const String& sourceURL) | |
+{ | |
+ if (!document()->hasListenerType(Document::BEFORELOAD_LISTENER)) | |
+ return true; | |
+ | |
+ RefPtr<ContainerNode> protector(this); | |
+ RefPtr<BeforeLoadEvent> beforeLoadEvent = BeforeLoadEvent::create(sourceURL); | |
+ dispatchEvent(beforeLoadEvent.get()); | |
+ return !beforeLoadEvent->defaultPrevented(); | |
+} | |
+ | |
+#if PLATFORM(WKC) | |
+void ContainerNode::deleteSharedInstance() | |
+{ | |
+ delete s_postAttachCallbackQueue; | |
+} | |
+ | |
+void ContainerNode::resetVariables() | |
+{ | |
+ s_postAttachCallbackQueue = 0; | |
+ s_attachDepth = 0; | |
+ s_shouldReEnableMemoryCacheCallsAfterAttach = false; | |
+} | |
+#endif | |
+ | |
+} // namespace WebCore | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Document.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Document.cpp | |
index c67cb7f..0b784eb 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Document.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Document.cpp | |
@@ -3,7 +3,7 @@ | |
* (C) 1999 Antti Koivisto (koivisto@kde.org) | |
* (C) 2001 Dirk Mueller (mueller@kde.org) | |
* (C) 2006 Alexey Proskuryakov (ap@webkit.org) | |
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | |
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. | |
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) | |
* Copyright (C) 2008, 2009 Google Inc. All rights reserved. | |
* Copyright (c) 2010-2013 ACCESS CO., LTD. All rights reserved. | |
@@ -204,6 +204,25 @@ using namespace HTMLNames; | |
// #define INSTRUMENT_LAYOUT_SCHEDULING 1 | |
+static const unsigned cMaxWriteRecursionDepth = 21; | |
+ | |
+class NestingLevelIncrementer { | |
+public: | |
+ explicit NestingLevelIncrementer(unsigned& nestingLevel) | |
+ : m_nestingLevel(&nestingLevel) | |
+ { | |
+ ++(*m_nestingLevel); | |
+ } | |
+ | |
+ ~NestingLevelIncrementer() | |
+ { | |
+ --(*m_nestingLevel); | |
+ } | |
+ | |
+private: | |
+ unsigned* m_nestingLevel; | |
+}; | |
+ | |
// This amount of time must have elapsed before we will even consider scheduling a layout without a delay. | |
// FIXME: For faster machines this value can really be lowered to 200. 250 is adequate, but a little high | |
// for dual G5s. :) | |
@@ -364,9 +383,12 @@ Document::Document(Frame* frame, bool isXHTML) | |
, m_hasOpenDatabases(false) | |
#endif | |
, m_usingGeolocation(false) | |
+ , m_idAttributeName(idAttr) | |
#if ENABLE(WML) | |
, m_containsWMLContent(false) | |
#endif | |
+ , m_writeRecursionIsTooDeep(false) | |
+ , m_writeRecursionDepth(0) | |
{ | |
m_document = this; | |
@@ -458,12 +480,7 @@ void Document::removedLastRef() | |
deleteAllValues(m_markers); | |
m_markers.clear(); | |
-#if PLATFORM(WKC) | |
- // cf. webkit.org trunk r65692 | |
detachTokenizer(); | |
-#else | |
- m_tokenizer.clear(); | |
-#endif | |
m_cssCanvasElements.clear(); | |
@@ -497,13 +514,8 @@ Document::~Document() | |
forgetAllDOMNodesForDocument(this); | |
#endif | |
-#if PLATFORM(WKC) | |
- // cf. webkit.org trunk r65692 | |
ASSERT(!m_tokenizer); | |
detachTokenizer(); | |
-#else | |
- m_tokenizer.clear(); | |
-#endif | |
m_document = 0; | |
delete m_styleSelector; | |
m_docLoader.clear(); | |
@@ -708,8 +720,14 @@ PassRefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionCo | |
return createComment(importedNode->nodeValue()); | |
case ELEMENT_NODE: { | |
Element* oldElement = static_cast<Element*>(importedNode); | |
- RefPtr<Element> newElement = createElementNS(oldElement->namespaceURI(), oldElement->tagQName().toString(), ec); | |
- | |
+ // FIXME: The following check might be unnecessary. Is it possible that | |
+ // oldElement has mismatched prefix/namespace? | |
+ if (hasPrefixNamespaceMismatch(oldElement->tagQName())) { | |
+ ec = NAMESPACE_ERR; | |
+ return 0; | |
+ } | |
+ RefPtr<Element> newElement = createElement(oldElement->tagQName(), ec); | |
+ | |
if (ec) | |
return 0; | |
@@ -1153,8 +1171,10 @@ void Document::removeElementById(const AtomicString& elementId, Element* element | |
{ | |
if (m_elementsById.get(elementId.impl()) == element) | |
m_elementsById.remove(elementId.impl()); | |
- else | |
+ else { | |
+ ASSERT(m_inRemovedLastRefFunction || m_duplicateIds.contains(elementId.impl())); | |
m_duplicateIds.remove(elementId.impl()); | |
+ } | |
} | |
Element* Document::getElementByAccessKey(const String& key) const | |
@@ -1209,7 +1229,7 @@ void Document::setTitle(const String& title, Element* titleElement) | |
m_title = title; | |
updateTitle(); | |
- if (m_titleSetExplicitly && m_titleElement && m_titleElement->hasTagName(titleTag)) | |
+ if (m_titleSetExplicitly && m_titleElement && m_titleElement->hasTagName(titleTag) && !titleElement) | |
static_cast<HTMLTitleElement*>(m_titleElement.get())->setText(m_title); | |
} | |
@@ -1460,9 +1480,8 @@ void Document::updateLayout() | |
updateStyleIfNeeded(); | |
- // Only do a layout if changes have occurred that make it necessary. | |
FrameView* v = view(); | |
- if (v && renderer() && (v->layoutPending() || renderer()->needsLayout())) | |
+ if (v && v->needsLayout()) | |
v->layout(); | |
} | |
@@ -1663,10 +1682,10 @@ void Document::setVisuallyOrdered() | |
renderer()->style()->setVisuallyOrdered(true); | |
} | |
-Tokenizer* Document::createTokenizer() | |
+PassRefPtr<Tokenizer> Document::createTokenizer() | |
{ | |
// FIXME: this should probably pass the frame instead | |
- return new XMLTokenizer(this, view()); | |
+ return XMLTokenizer::create(this, view()); | |
} | |
void Document::open(Document* ownerDocument) | |
@@ -1694,20 +1713,13 @@ void Document::open(Document* ownerDocument) | |
m_frame->loader()->didExplicitOpen(); | |
} | |
-#if PLATFORM(WKC) | |
-// cf. webkit.org trunk r65692 | |
void Document::detachTokenizer() | |
{ | |
if (!m_tokenizer) | |
return; | |
- bool detached = m_tokenizer->detach(); | |
- if (detached) { | |
- m_tokenizer.clear(); | |
- } else { | |
- m_tokenizer.release(); | |
- } | |
+ m_tokenizer->detach(); | |
+ m_tokenizer.clear(); | |
} | |
-#endif | |
void Document::cancelParsing() | |
{ | |
@@ -1716,12 +1728,7 @@ void Document::cancelParsing() | |
// the onload handler when closing as a side effect of a cancel-style | |
// change, such as opening a new document or closing the window while | |
// still parsing | |
-#if PLATFORM(WKC) | |
- // cf. webkit.org trunk r65692 | |
detachTokenizer(); | |
-#else | |
- m_tokenizer.clear(); | |
-#endif | |
close(); | |
} | |
} | |
@@ -1730,11 +1737,6 @@ void Document::implicitOpen() | |
{ | |
cancelParsing(); | |
-#if 0 | |
- // cf. webkit.org trunk r65692 | |
- m_tokenizer.clear(); | |
-#endif | |
- | |
removeChildren(); | |
m_tokenizer = createTokenizer(); | |
@@ -1834,12 +1836,7 @@ void Document::implicitClose() | |
// We have to clear the tokenizer, in case someone document.write()s from the | |
// onLoad event handler, as in Radar 3206524. | |
-#if PLATFORM(WKC) | |
- // cf. webkit.org trunk r65692 | |
detachTokenizer(); | |
-#else | |
- m_tokenizer.clear(); | |
-#endif | |
// Parser should have picked up all preloads by now | |
m_docLoader->clearPreloads(); | |
@@ -1982,6 +1979,14 @@ int Document::elapsedTime() const | |
void Document::write(const SegmentedString& text, Document* ownerDocument) | |
{ | |
+ NestingLevelIncrementer nestingLevelIncrementer(m_writeRecursionDepth); | |
+ | |
+ m_writeRecursionIsTooDeep = (m_writeRecursionDepth > 1) && m_writeRecursionIsTooDeep; | |
+ m_writeRecursionIsTooDeep = (m_writeRecursionDepth > cMaxWriteRecursionDepth) || m_writeRecursionIsTooDeep; | |
+ | |
+ if (m_writeRecursionIsTooDeep) | |
+ return; | |
+ | |
#ifdef INSTRUMENT_LAYOUT_SCHEDULING | |
if (!ownerElement()) | |
printf("Beginning a document.write at %d\n", elapsedTime()); | |
@@ -2425,10 +2430,12 @@ void Document::processHttpEquiv(const String& equiv, const String& content) | |
else if (equalIgnoringCase(equiv, "x-dns-prefetch-control")) | |
parseDNSPrefetchControlHeader(content); | |
else if (equalIgnoringCase(equiv, "x-frame-options")) { | |
- FrameLoader* frameLoader = frame->loader(); | |
- if (frameLoader->shouldInterruptLoadForXFrameOptions(content, url())) { | |
- frameLoader->stopAllLoaders(); | |
- frame->redirectScheduler()->scheduleLocationChange(blankURL(), String()); | |
+ if (frame) { | |
+ FrameLoader* frameLoader = frame->loader(); | |
+ if (frameLoader->shouldInterruptLoadForXFrameOptions(content, url())) { | |
+ frameLoader->stopAllLoaders(); | |
+ frame->redirectScheduler()->scheduleLocationChange(blankURL(), String()); | |
+ } | |
} | |
} | |
} | |
@@ -3022,9 +3029,23 @@ void Document::attachNodeIterator(NodeIterator *ni) | |
void Document::detachNodeIterator(NodeIterator *ni) | |
{ | |
+ // The node iterator can be detached without having been attached if its root node didn't have a document | |
+ // when the iterator was created, but has it now. | |
m_nodeIterators.remove(ni); | |
} | |
+void Document::moveNodeIteratorsToNewDocument(Node* node, Document* newDocument) | |
+{ | |
+ HashSet<NodeIterator*> nodeIteratorsList = m_nodeIterators; | |
+ HashSet<NodeIterator*>::const_iterator nodeIteratorsEnd = nodeIteratorsList.end(); | |
+ for (HashSet<NodeIterator*>::const_iterator it = nodeIteratorsList.begin(); it != nodeIteratorsEnd; ++it) { | |
+ if ((*it)->root() == node) { | |
+ detachNodeIterator(*it); | |
+ newDocument->attachNodeIterator(*it); | |
+ } | |
+ } | |
+} | |
+ | |
void Document::nodeChildrenChanged(ContainerNode* container) | |
{ | |
if (!disableRangeMutation(page())) { | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Document.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Document.h | |
index 6468edd..70df114 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Document.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Document.h | |
@@ -36,6 +36,7 @@ | |
#include "DocumentMarker.h" | |
#include "ScriptExecutionContext.h" | |
#include "Timer.h" | |
+#include "QualifiedName.h" | |
#if USE(JSC) | |
#include <runtime/WeakGCMap.h> | |
#endif | |
@@ -514,7 +515,7 @@ public: | |
CSSStyleSheet* elementSheet(); | |
CSSStyleSheet* mappedElementSheet(); | |
- virtual Tokenizer* createTokenizer(); | |
+ virtual PassRefPtr<Tokenizer> createTokenizer(); | |
Tokenizer* tokenizer() { return m_tokenizer.get(); } | |
bool printing() const { return m_printing; } | |
@@ -600,6 +601,7 @@ public: | |
void attachNodeIterator(NodeIterator*); | |
void detachNodeIterator(NodeIterator*); | |
+ void moveNodeIteratorsToNewDocument(Node*, Document*); | |
void attachRange(Range*); | |
void detachRange(Range*); | |
@@ -927,6 +929,8 @@ public: | |
bool processingLoadEvent() const { return m_processingLoadEvent; } | |
+ const QualifiedName& idAttributeName() const { return m_idAttributeName; } | |
+ | |
#if ENABLE(DATABASE) | |
void addOpenDatabase(Database*); | |
void removeOpenDatabase(Database*); | |
@@ -960,10 +964,7 @@ protected: | |
void clearXMLVersion() { m_xmlVersion = String(); } | |
private: | |
-#if PLATFORM(WKC) | |
- // cf. webkit.org trunk r65692 | |
void detachTokenizer(); | |
-#endif | |
virtual bool isDocument() const { return true; } | |
virtual void removedLastRef(); | |
@@ -1000,7 +1001,7 @@ private: | |
Frame* m_frame; | |
OwnPtr<DocLoader> m_docLoader; | |
- OwnPtr<Tokenizer> m_tokenizer; | |
+ RefPtr<Tokenizer> m_tokenizer; | |
bool m_wellFormed; | |
// Document URLs. | |
@@ -1219,9 +1220,13 @@ private: | |
bool m_usingGeolocation; | |
+ QualifiedName m_idAttributeName; | |
+ | |
#if ENABLE(WML) | |
bool m_containsWMLContent; | |
#endif | |
+ bool m_writeRecursionIsTooDeep; | |
+ unsigned m_writeRecursionDepth; | |
}; | |
inline bool Document::hasElementWithId(AtomicStringImpl* id) const | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Element.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Element.cpp | |
index adaba4d..b9db249 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Element.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Element.cpp | |
@@ -237,6 +237,15 @@ Node::NodeType Element::nodeType() const | |
return ELEMENT_NODE; | |
} | |
+bool Element::isIdAttributeName(const QualifiedName& attributeName) const | |
+{ | |
+ // FIXME: This check is probably not correct for the case where the document has an id attribute | |
+ // with a non-null namespace, because it will return false, a false negative, if the prefixes | |
+ // don't match but the local name and namespace both do. However, since this has been like this | |
+ // for a while and the code paths may be hot, we'll have to measure performance if we fix it. | |
+ return attributeName == document()->idAttributeName(); | |
+} | |
+ | |
const AtomicString& Element::getIDAttribute() const | |
{ | |
return namedAttrMap ? namedAttrMap->id() : nullAtom; | |
@@ -598,7 +607,10 @@ void Element::setAttribute(const AtomicString& name, const AtomicString& value, | |
else if (!old && !value.isNull()) | |
namedAttrMap->addAttribute(createAttribute(QualifiedName(nullAtom, localName, nullAtom), value)); | |
else if (old && !value.isNull()) { | |
- old->setValue(value); | |
+ if (Attr* attrNode = old->attr()) | |
+ attrNode->setValue(value); | |
+ else | |
+ old->setValue(value); | |
attributeChanged(old); | |
} | |
} | |
@@ -618,7 +630,10 @@ void Element::setAttribute(const QualifiedName& name, const AtomicString& value, | |
else if (!old && !value.isNull()) | |
namedAttrMap->addAttribute(createAttribute(name, value)); | |
else if (old) { | |
- old->setValue(value); | |
+ if (Attr* attrNode = old->attr()) | |
+ attrNode->setValue(value); | |
+ else | |
+ old->setValue(value); | |
attributeChanged(old); | |
} | |
} | |
@@ -970,6 +985,15 @@ bool Element::childTypeAllowed(NodeType type) | |
} | |
} | |
+static void checkForEmptyStyleChange(Element* element, RenderStyle* style) | |
+{ | |
+ if (!style) | |
+ return; | |
+ | |
+ if (style->affectedByEmpty() && (!style->emptyState() || element->hasChildNodes())) | |
+ element->setNeedsStyleRecalc(); | |
+} | |
+ | |
static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback, | |
Node* beforeChange, Node* afterChange, int childCountDelta) | |
{ | |
@@ -1046,14 +1070,15 @@ static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool fin | |
e->setNeedsStyleRecalc(); | |
// :empty selector. | |
- if (style->affectedByEmpty() && (!style->emptyState() || e->hasChildNodes())) | |
- e->setNeedsStyleRecalc(); | |
+ checkForEmptyStyleChange(e, style); | |
} | |
void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) | |
{ | |
ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); | |
- if (!changedByParser) | |
+ if (changedByParser) | |
+ checkForEmptyStyleChange(this, renderStyle()); | |
+ else | |
checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta); | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Element.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Element.h | |
index cd9bbc6..9b063bc 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Element.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Element.h | |
@@ -104,6 +104,7 @@ public: | |
virtual PassRefPtr<DocumentFragment> createContextualFragment(const String&); | |
#endif | |
+ bool isIdAttributeName(const QualifiedName&) const; | |
const AtomicString& getIDAttribute() const; | |
bool hasAttribute(const QualifiedName&) const; | |
const AtomicString& getAttribute(const QualifiedName&) const; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/MessagePort.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/MessagePort.cpp | |
index 1051920..8e37ad9 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/MessagePort.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/MessagePort.cpp | |
@@ -20,7 +20,7 @@ | |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
* | |
*/ | |
@@ -72,7 +72,7 @@ void MessagePort::postMessage(PassRefPtr<SerializedScriptValue> message, Excepti | |
void MessagePort::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionCode& ec) | |
{ | |
- if (!m_entangledChannel) | |
+ if (!isEntangled()) | |
return; | |
ASSERT(m_scriptExecutionContext); | |
@@ -118,8 +118,8 @@ void MessagePort::messageAvailable() | |
void MessagePort::start() | |
{ | |
- // Do nothing if we've been cloned | |
- if (!m_entangledChannel) | |
+ // Do nothing if we've been cloned or closed. | |
+ if (!isEntangled()) | |
return; | |
ASSERT(m_scriptExecutionContext); | |
@@ -133,7 +133,7 @@ void MessagePort::start() | |
void MessagePort::close() | |
{ | |
m_closed = true; | |
- if (!m_entangledChannel) | |
+ if (!isEntangled()) | |
return; | |
m_entangledChannel->close(); | |
} | |
@@ -152,8 +152,9 @@ void MessagePort::entangle(PassOwnPtr<MessagePortChannel> remote) | |
void MessagePort::contextDestroyed() | |
{ | |
ASSERT(m_scriptExecutionContext); | |
- // Must close port before blowing away the cached context, to ensure that we get no more calls to messageAvailable(). | |
- close(); | |
+ // Must be closed before blowing away the cached context, to ensure that we get no more calls to messageAvailable(). | |
+ // ScriptExecutionContext::closeMessagePorts() takes care of that. | |
+ ASSERT(m_closed); | |
m_scriptExecutionContext = 0; | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Node.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Node.cpp | |
index deaad9d..5419f62 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Node.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Node.cpp | |
@@ -559,8 +559,10 @@ void Node::setDocument(Document* document) | |
updateDOMNodeDocument(this, m_document, document); | |
#endif | |
- if (m_document) | |
+ if (m_document) { | |
+ m_document->moveNodeIteratorsToNewDocument(this, document); | |
m_document->selfOnlyDeref(); | |
+ } | |
m_document = document; | |
@@ -994,8 +996,18 @@ void Node::notifyLocalNodeListsChildrenChanged() | |
void Node::notifyNodeListsChildrenChanged() | |
{ | |
+#if !PLATFORM(WKC) | |
for (Node* n = this; n; n = n->parentNode()) | |
n->notifyLocalNodeListsChildrenChanged(); | |
+#else | |
+ Vector<Node*> visited; | |
+ for (Node* n = this; n; n = n->parentNode()) { | |
+ if (visited.find(n)!=notFound) | |
+ break; | |
+ n->notifyLocalNodeListsChildrenChanged(); | |
+ visited.append(n); | |
+ } | |
+#endif | |
} | |
Node *Node::traverseNextNode(const Node *stayWithin) const | |
@@ -1127,8 +1139,7 @@ bool Node::canReplaceChild(Node* newChild, Node*) | |
void Node::checkReplaceChild(Node* newChild, Node* oldChild, ExceptionCode& ec) | |
{ | |
- // Perform error checking as required by spec for adding a new child. Used by | |
- // appendChild(), replaceChild() and insertBefore() | |
+ // Perform error checking as required by spec for adding a new child. Used by replaceChild(). | |
// Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null | |
if (!newChild) { | |
@@ -1183,8 +1194,7 @@ void Node::checkReplaceChild(Node* newChild, Node* oldChild, ExceptionCode& ec) | |
void Node::checkAddChild(Node *newChild, ExceptionCode& ec) | |
{ | |
- // Perform error checking as required by spec for adding a new child. Used by | |
- // appendChild(), replaceChild() and insertBefore() | |
+ // Perform error checking as required by spec for adding a new child. Used by appendChild() and insertBefore(). | |
// Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null | |
if (!newChild) { | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/NodeIterator.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/NodeIterator.cpp | |
index af07f42..ce3103c 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/NodeIterator.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/NodeIterator.cpp | |
@@ -76,12 +76,16 @@ NodeIterator::NodeIterator(PassRefPtr<Node> rootNode, unsigned whatToShow, PassR | |
, m_referenceNode(root(), true) | |
, m_detached(false) | |
{ | |
- root()->document()->attachNodeIterator(this); | |
+ // Document type nodes may have a null document. But since they can't have children, there is no need to listen for modifications to these. | |
+ ASSERT(root()->document() || root()->nodeType() == Node::DOCUMENT_TYPE_NODE); | |
+ if (Document* ownerDocument = root()->document()) | |
+ ownerDocument->attachNodeIterator(this); | |
} | |
NodeIterator::~NodeIterator() | |
{ | |
- root()->document()->detachNodeIterator(this); | |
+ if (Document* ownerDocument = root()->document()) | |
+ ownerDocument->detachNodeIterator(this); | |
} | |
PassRefPtr<Node> NodeIterator::nextNode(ScriptState* state, ExceptionCode& ec) | |
@@ -144,7 +148,8 @@ PassRefPtr<Node> NodeIterator::previousNode(ScriptState* state, ExceptionCode& e | |
void NodeIterator::detach() | |
{ | |
- root()->document()->detachNodeIterator(this); | |
+ if (Document* ownerDocument = root()->document()) | |
+ ownerDocument->detachNodeIterator(this); | |
m_detached = true; | |
m_referenceNode.node.clear(); | |
} | |
@@ -159,6 +164,7 @@ void NodeIterator::updateForNodeRemoval(Node* removedNode, NodePointer& referenc | |
{ | |
ASSERT(!m_detached); | |
ASSERT(removedNode); | |
+ ASSERT(root()->document()); | |
ASSERT(root()->document() == removedNode->document()); | |
// Iterator is not affected if the removed node is the reference node and is the root. | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Position.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Position.cpp | |
index c83965b..0a05b4c 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Position.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Position.cpp | |
@@ -482,6 +482,9 @@ Position Position::upstream(EditingBoundaryCrossingRule rule) const | |
bool startEditable = startNode->isContentEditable(); | |
Node* lastNode = startNode; | |
bool boundaryCrossed = false; | |
+#if PLATFORM(WKC) | |
+ int loops = 0; | |
+#endif | |
for (; !currentPos.atStart(); currentPos.decrement()) { | |
Node* currentNode = currentPos.node(); | |
@@ -579,6 +582,11 @@ Position Position::upstream(EditingBoundaryCrossingRule rule) const | |
return currentPos; | |
} | |
} | |
+#if PLATFORM(WKC) | |
+ loops++; | |
+ if (loops > 16383) | |
+ return Position(); | |
+#endif | |
} | |
return lastVisible; | |
@@ -989,29 +997,56 @@ static InlineTextBox* searchAheadForBetterMatch(RenderObject* renderer) | |
return 0; | |
} | |
+static Position downstreamIgnoringEditingBoundaries(Position position) | |
+{ | |
+ Position lastPosition; | |
+ while (position != lastPosition) { | |
+ lastPosition = position; | |
+ position = position.downstream(Position::CanCrossEditingBoundary); | |
+ } | |
+ return position; | |
+} | |
+ | |
+static Position upstreamIgnoringEditingBoundaries(Position position) | |
+{ | |
+ Position lastPosition; | |
+ while (position != lastPosition) { | |
+ lastPosition = position; | |
+ position = position.upstream(Position::CanCrossEditingBoundary); | |
+ } | |
+ return position; | |
+} | |
+ | |
void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const | |
{ | |
caretOffset = m_offset; | |
RenderObject* renderer = node()->renderer(); | |
if (!renderer->isText()) { | |
- if (!renderer->isRenderButton() && renderer->isBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) { | |
- bool lastPosition = caretOffset == lastOffsetInNode(node()); | |
- Node* startNode = lastPosition ? node()->childNode(caretOffset - 1) : node()->childNode(caretOffset); | |
- while (startNode && (!startNode->renderer() || (startNode->isTextNode() && toRenderText(startNode->renderer())->isAllCollapsibleWhitespace()))) | |
- startNode = (lastPosition)? startNode->previousSibling(): startNode->nextSibling(); | |
- if (startNode) { | |
- Position pos(startNode, 0); | |
- pos = pos.downstream(CanCrossEditingBoundary); | |
- pos.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineBox, caretOffset); | |
- if (lastPosition && inlineBox) | |
- caretOffset = inlineBox->caretMaxOffset(); | |
- return; | |
+ inlineBox = 0; | |
+ if (canHaveChildrenForEditing(node()) && renderer->isBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) { | |
+ // Try a visually equivalent position with possibly opposite editability. This helps in case |this| is in | |
+ // an editable block but surrounded by non-editable positions. It acts to negate the logic at the beginning | |
+ // of RenderObject::createVisiblePosition(). | |
+ Position equivalent = downstreamIgnoringEditingBoundaries(*this); | |
+ if (equivalent == *this) { | |
+ equivalent = upstreamIgnoringEditingBoundaries(*this); | |
+ if (equivalent == *this || downstreamIgnoringEditingBoundaries(equivalent) == *this) | |
+ return; | |
} | |
+ | |
+ equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineBox, caretOffset); | |
+ return; | |
} | |
- inlineBox = renderer->isBox() ? toRenderBox(renderer)->inlineBoxWrapper() : 0; | |
- if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset())) | |
+ if (renderer->isBox()) { | |
+ inlineBox = toRenderBox(renderer)->inlineBoxWrapper(); | |
+ if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset())) | |
+ return; | |
+ } else if (!node()->isLink() && node()->isContentEditable()) { | |
+ Position pos = positionInParentBeforeNode(node()).upstream(); | |
+ pos.getInlineBoxAndOffset(DOWNSTREAM, primaryDirection, inlineBox, caretOffset); | |
return; | |
+ } | |
} else { | |
RenderText* textRenderer = toRenderText(renderer); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Range.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Range.cpp | |
index a72edcc..2b46e29 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Range.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Range.cpp | |
@@ -3,7 +3,7 @@ | |
* (C) 2000 Gunnstein Lye (gunnstein@netcom.no) | |
* (C) 2000 Frederik Holljen (frederik.holljen@hig.no) | |
* (C) 2001 Peter Kelly (pmk@post.com) | |
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | |
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. | |
* Copyright (c) 2010 ACCESS CO., LTD. All rights reserved. | |
* | |
* This library is free software; you can redistribute it and/or | |
@@ -42,9 +42,12 @@ | |
#include "visible_units.h" | |
#include <stdio.h> | |
#include <wtf/RefCountedLeakCounter.h> | |
+#include <wtf/Vector.h> | |
namespace WebCore { | |
+typedef Vector<RefPtr<Node> > NodeVector; | |
+ | |
using namespace std; | |
#ifndef NDEBUG | |
@@ -99,9 +102,7 @@ inline Range::Range(PassRefPtr<Document> ownerDocument, PassRefPtr<Node> startCo | |
// that setStart and setEnd do, so we call those functions. | |
ExceptionCode ec = 0; | |
setStart(startContainer, startOffset, ec); | |
- ASSERT(!ec); | |
setEnd(endContainer, endOffset, ec); | |
- ASSERT(!ec); | |
} | |
PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset) | |
@@ -128,6 +129,17 @@ Range::~Range() | |
#endif | |
} | |
+void Range::setDocument(Document* document) | |
+{ | |
+ ASSERT(m_ownerDocument != document); | |
+ if (m_ownerDocument) | |
+ m_ownerDocument->detachRange(this); | |
+ m_ownerDocument = document; | |
+ m_start.setToStartOfNode(document); | |
+ m_end.setToStartOfNode(document); | |
+ m_ownerDocument->attachRange(this); | |
+} | |
+ | |
Node* Range::startContainer(ExceptionCode& ec) const | |
{ | |
if (!m_start.container()) { | |
@@ -603,11 +615,66 @@ bool Range::intersectsNode(Node* refNode, ExceptionCode& ec) | |
return true; // all other cases | |
} | |
-PassRefPtr<DocumentFragment> Range::processContents(ActionType action, ExceptionCode& ec) | |
+static inline Node* highestAncestorUnderCommonRoot(Node* node, Node* commonRoot) | |
+{ | |
+ if (node == commonRoot) | |
+ return 0; | |
+ | |
+ ASSERT(commonRoot->contains(node)); | |
+ | |
+ while (node->parentNode() != commonRoot) | |
+ node = node->parentNode(); | |
+ | |
+ return node; | |
+} | |
+ | |
+static inline Node* childOfCommonRootBeforeOffset(Node* container, unsigned offset, Node* commonRoot) | |
{ | |
- // FIXME: To work properly with mutation events, we will have to take into account | |
- // situations where the tree is being transformed while we work on it - ugh! | |
+ ASSERT(container); | |
+ ASSERT(commonRoot); | |
+ | |
+ if (!commonRoot->contains(container)) | |
+ return 0; | |
+ | |
+ if (container == commonRoot) { | |
+ container = container->firstChild(); | |
+ for (unsigned i = 0; container && i < offset; i++) | |
+ container = container->nextSibling(); | |
+ } else { | |
+ while (container->parentNode() != commonRoot) | |
+ container = container->parentNode(); | |
+ } | |
+ | |
+ return container; | |
+} | |
+ | |
+static inline unsigned lengthOfContentsInNode(Node* node) | |
+{ | |
+ // This switch statement must be consistent with that of Range::processContentsBetweenOffsets. | |
+ switch (node->nodeType()) { | |
+ case Node::TEXT_NODE: | |
+ case Node::CDATA_SECTION_NODE: | |
+ case Node::COMMENT_NODE: | |
+ return static_cast<CharacterData*>(node)->length(); | |
+ case Node::PROCESSING_INSTRUCTION_NODE: | |
+ return static_cast<ProcessingInstruction*>(node)->data().length(); | |
+ case Node::ELEMENT_NODE: | |
+ case Node::ATTRIBUTE_NODE: | |
+ case Node::ENTITY_REFERENCE_NODE: | |
+ case Node::ENTITY_NODE: | |
+ case Node::DOCUMENT_NODE: | |
+ case Node::DOCUMENT_TYPE_NODE: | |
+ case Node::DOCUMENT_FRAGMENT_NODE: | |
+ case Node::NOTATION_NODE: | |
+ case Node::XPATH_NAMESPACE_NODE: | |
+ return node->childNodeCount(); | |
+ } | |
+ ASSERT_NOT_REACHED(); | |
+ return 0; | |
+} | |
+PassRefPtr<DocumentFragment> Range::processContents(ActionType action, ExceptionCode& ec) | |
+{ | |
RefPtr<DocumentFragment> fragment; | |
if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) | |
fragment = DocumentFragment::create(m_ownerDocument.get()); | |
@@ -618,75 +685,18 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception | |
if (ec) | |
return 0; | |
- Node* commonRoot = commonAncestorContainer(ec); | |
+ RefPtr<Node> commonRoot = commonAncestorContainer(ec); | |
if (ec) | |
return 0; | |
ASSERT(commonRoot); | |
// what is the highest node that partially selects the start of the range? | |
- Node* partialStart = 0; | |
- if (m_start.container() != commonRoot) { | |
- partialStart = m_start.container(); | |
- while (partialStart->parentNode() != commonRoot) | |
- partialStart = partialStart->parentNode(); | |
- } | |
- | |
- // what is the highest node that partially selects the end of the range? | |
- Node* partialEnd = 0; | |
- if (m_end.container() != commonRoot) { | |
- partialEnd = m_end.container(); | |
- while (partialEnd->parentNode() != commonRoot) | |
- partialEnd = partialEnd->parentNode(); | |
- } | |
- | |
- // Simple case: the start and end containers are the same. We just grab | |
- // everything >= start offset and < end offset | |
- if (m_start.container() == m_end.container()) { | |
- Node::NodeType startNodeType = m_start.container()->nodeType(); | |
- if (startNodeType == Node::TEXT_NODE || startNodeType == Node::CDATA_SECTION_NODE || startNodeType == Node::COMMENT_NODE) { | |
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | |
- RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_start.container()->cloneNode(true)); | |
- c->deleteData(m_end.offset(), c->length() - m_end.offset(), ec); | |
- c->deleteData(0, m_start.offset(), ec); | |
- fragment->appendChild(c.release(), ec); | |
- } | |
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) | |
- static_cast<CharacterData*>(m_start.container())->deleteData(m_start.offset(), m_end.offset() - m_start.offset(), ec); | |
- } else if (startNodeType == Node::PROCESSING_INSTRUCTION_NODE) { | |
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | |
- RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(m_start.container()->cloneNode(true)); | |
- c->setData(c->data().substring(m_start.offset(), m_end.offset() - m_start.offset()), ec); | |
- fragment->appendChild(c.release(), ec); | |
- } | |
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | |
- ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(m_start.container()); | |
- String data(pi->data()); | |
- data.remove(m_start.offset(), m_end.offset() - m_start.offset()); | |
- pi->setData(data, ec); | |
- } | |
- } else { | |
- Node* n = m_start.container()->firstChild(); | |
- int i; | |
- for (i = 0; n && i < m_start.offset(); i++) // skip until start offset | |
- n = n->nextSibling(); | |
- int endOffset = m_end.offset(); | |
- while (n && i < endOffset) { // delete until end offset | |
- Node* next = n->nextSibling(); | |
- if (action == EXTRACT_CONTENTS) | |
- fragment->appendChild(n, ec); // will remove n from its parent | |
- else if (action == CLONE_CONTENTS) | |
- fragment->appendChild(n->cloneNode(true), ec); | |
- else | |
- m_start.container()->removeChild(n, ec); | |
- n = next; | |
- i++; | |
- } | |
- } | |
- return fragment.release(); | |
- } | |
+ // what is the highest node that partially selects the start / end of the range? | |
+ RefPtr<Node> partialStart = highestAncestorUnderCommonRoot(m_start.container(), commonRoot.get()); | |
+ RefPtr<Node> partialEnd = highestAncestorUnderCommonRoot(m_end.container(), commonRoot.get()); | |
- // Complex case: Start and end containers are different. | |
- // There are three possiblities here: | |
+ // Start and end containers are different. | |
+ // There are three possibilities here: | |
// 1. Start container == commonRoot (End container must be a descendant) | |
// 2. End container == commonRoot (Start container must be a descendant) | |
// 3. Neither is commonRoot, they are both descendants | |
@@ -702,170 +712,32 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception | |
// | |
// These are deleted, cloned, or extracted (i.e. both) depending on action. | |
- RefPtr<Node> leftContents; | |
- if (m_start.container() != commonRoot) { | |
- // process the left-hand side of the range, up until the last ancestor of | |
- // start container before commonRoot | |
- Node::NodeType startNodeType = m_start.container()->nodeType(); | |
- if (startNodeType == Node::TEXT_NODE || startNodeType == Node::CDATA_SECTION_NODE || startNodeType == Node::COMMENT_NODE) { | |
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | |
- RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_start.container()->cloneNode(true)); | |
- c->deleteData(0, m_start.offset(), ec); | |
- leftContents = c.release(); | |
- } | |
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) | |
- static_cast<CharacterData*>(m_start.container())->deleteData( | |
- m_start.offset(), static_cast<CharacterData*>(m_start.container())->length() - m_start.offset(), ec); | |
- } else if (startNodeType == Node::PROCESSING_INSTRUCTION_NODE) { | |
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | |
- RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(m_start.container()->cloneNode(true)); | |
- c->setData(c->data().substring(m_start.offset()), ec); | |
- leftContents = c.release(); | |
- } | |
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | |
- ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(m_start.container()); | |
- String data(pi->data()); | |
- pi->setData(data.left(m_start.offset()), ec); | |
- } | |
- } else { | |
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) | |
- leftContents = m_start.container()->cloneNode(false); | |
- Node* n = m_start.container()->firstChild(); | |
- for (int i = 0; n && i < m_start.offset(); i++) // skip until start offset | |
- n = n->nextSibling(); | |
- while (n) { // process until end | |
- Node* next = n->nextSibling(); | |
- if (action == EXTRACT_CONTENTS) | |
- leftContents->appendChild(n, ec); // will remove n from start container | |
- else if (action == CLONE_CONTENTS) | |
- leftContents->appendChild(n->cloneNode(true), ec); | |
- else | |
- m_start.container()->removeChild(n, ec); | |
- n = next; | |
- } | |
- } | |
- | |
- Node* leftParent = m_start.container()->parentNode(); | |
- Node* n = m_start.container()->nextSibling(); | |
- for (; leftParent != commonRoot; leftParent = leftParent->parentNode()) { | |
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | |
- RefPtr<Node> leftContentsParent = leftParent->cloneNode(false); | |
- leftContentsParent->appendChild(leftContents, ec); | |
- leftContents = leftContentsParent; | |
- } | |
+ // Note that we are verifying that our common root hierarchy is still intact | |
+ // after any DOM mutation event, at various stages below. See webkit bug 60350. | |
- Node* next; | |
- for (; n; n = next) { | |
- next = n->nextSibling(); | |
- if (action == EXTRACT_CONTENTS) | |
- leftContents->appendChild(n, ec); // will remove n from leftParent | |
- else if (action == CLONE_CONTENTS) | |
- leftContents->appendChild(n->cloneNode(true), ec); | |
- else | |
- leftParent->removeChild(n, ec); | |
- } | |
- n = leftParent->nextSibling(); | |
- } | |
+ RefPtr<Node> leftContents; | |
+ if (m_start.container() != commonRoot && commonRoot->contains(m_start.container())) { | |
+ leftContents = processContentsBetweenOffsets(action, 0, m_start.container(), m_start.offset(), lengthOfContentsInNode(m_start.container()), ec); | |
+ leftContents = processAncestorsAndTheirSiblings(action, m_start.container(), ProcessContentsForward, leftContents, commonRoot.get(), ec); | |
} | |
RefPtr<Node> rightContents; | |
- if (m_end.container() != commonRoot) { | |
- // delete the right-hand side of the range, up until the last ancestor of | |
- // end container before commonRoot | |
- Node::NodeType endNodeType = m_end.container()->nodeType(); | |
- if (endNodeType == Node::TEXT_NODE || endNodeType == Node::CDATA_SECTION_NODE || endNodeType == Node::COMMENT_NODE) { | |
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | |
- RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_end.container()->cloneNode(true)); | |
- c->deleteData(m_end.offset(), static_cast<CharacterData*>(m_end.container())->length() - m_end.offset(), ec); | |
- rightContents = c; | |
- } | |
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) | |
- static_cast<CharacterData*>(m_end.container())->deleteData(0, m_end.offset(), ec); | |
- } else if (endNodeType == Node::PROCESSING_INSTRUCTION_NODE) { | |
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | |
- RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(m_end.container()->cloneNode(true)); | |
- c->setData(c->data().left(m_end.offset()), ec); | |
- rightContents = c.release(); | |
- } | |
- if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | |
- ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(m_end.container()); | |
- pi->setData(pi->data().substring(m_end.offset()), ec); | |
- } | |
- } else { | |
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) | |
- rightContents = m_end.container()->cloneNode(false); | |
- Node* n = m_end.container()->firstChild(); | |
- if (n && m_end.offset()) { | |
- for (int i = 0; i + 1 < m_end.offset(); i++) { // skip to end.offset() | |
- Node* next = n->nextSibling(); | |
- if (!next) | |
- break; | |
- n = next; | |
- } | |
- Node* prev; | |
- for (; n; n = prev) { | |
- prev = n->previousSibling(); | |
- if (action == EXTRACT_CONTENTS) | |
- rightContents->insertBefore(n, rightContents->firstChild(), ec); // will remove n from its parent | |
- else if (action == CLONE_CONTENTS) | |
- rightContents->insertBefore(n->cloneNode(true), rightContents->firstChild(), ec); | |
- else | |
- m_end.container()->removeChild(n, ec); | |
- } | |
- } | |
- } | |
- | |
- Node* rightParent = m_end.container()->parentNode(); | |
- Node* n = m_end.container()->previousSibling(); | |
- for (; rightParent != commonRoot; rightParent = rightParent->parentNode()) { | |
- if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | |
- RefPtr<Node> rightContentsParent = rightParent->cloneNode(false); | |
- rightContentsParent->appendChild(rightContents, ec); | |
- rightContents = rightContentsParent; | |
- } | |
- Node* prev; | |
- for (; n; n = prev) { | |
- prev = n->previousSibling(); | |
- if (action == EXTRACT_CONTENTS) | |
- rightContents->insertBefore(n, rightContents->firstChild(), ec); // will remove n from its parent | |
- else if (action == CLONE_CONTENTS) | |
- rightContents->insertBefore(n->cloneNode(true), rightContents->firstChild(), ec); | |
- else | |
- rightParent->removeChild(n, ec); | |
- } | |
- n = rightParent->previousSibling(); | |
- } | |
+ if (m_end.container() != commonRoot && commonRoot->contains(m_end.container())) { | |
+ rightContents = processContentsBetweenOffsets(action, 0, m_end.container(), 0, m_end.offset(), ec); | |
+ rightContents = processAncestorsAndTheirSiblings(action, m_end.container(), ProcessContentsBackward, rightContents, commonRoot.get(), ec); | |
} | |
// delete all children of commonRoot between the start and end container | |
- | |
- Node* processStart; // child of commonRoot | |
- if (m_start.container() == commonRoot) { | |
- processStart = m_start.container()->firstChild(); | |
- for (int i = 0; i < m_start.offset(); i++) | |
- processStart = processStart->nextSibling(); | |
- } else { | |
- processStart = m_start.container(); | |
- while (processStart->parentNode() != commonRoot) | |
- processStart = processStart->parentNode(); | |
+ RefPtr<Node> processStart = childOfCommonRootBeforeOffset(m_start.container(), m_start.offset(), commonRoot.get()); | |
+ if (processStart && m_start.container() != commonRoot) // processStart contains nodes before m_start. | |
processStart = processStart->nextSibling(); | |
- } | |
- Node* processEnd; // child of commonRoot | |
- if (m_end.container() == commonRoot) { | |
- processEnd = m_end.container()->firstChild(); | |
- for (int i = 0; i < m_end.offset(); i++) | |
- processEnd = processEnd->nextSibling(); | |
- } else { | |
- processEnd = m_end.container(); | |
- while (processEnd->parentNode() != commonRoot) | |
- processEnd = processEnd->parentNode(); | |
- } | |
+ RefPtr<Node> processEnd = childOfCommonRootBeforeOffset(m_end.container(), m_end.offset(), commonRoot.get()); | |
// Collapse the range, making sure that the result is not within a node that was partially selected. | |
if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | |
- if (partialStart) | |
+ if (partialStart && commonRoot->contains(partialStart.get())) | |
setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1, ec); | |
- else if (partialEnd) | |
+ else if (partialEnd && commonRoot->contains(partialEnd.get())) | |
setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), ec); | |
if (ec) | |
return 0; | |
@@ -878,18 +750,11 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception | |
if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents) | |
fragment->appendChild(leftContents, ec); | |
- Node* next; | |
- Node* n; | |
if (processStart) { | |
- for (n = processStart; n && n != processEnd; n = next) { | |
- next = n->nextSibling(); | |
- if (action == EXTRACT_CONTENTS) | |
- fragment->appendChild(n, ec); // will remove from commonRoot | |
- else if (action == CLONE_CONTENTS) | |
- fragment->appendChild(n->cloneNode(true), ec); | |
- else | |
- commonRoot->removeChild(n, ec); | |
- } | |
+ NodeVector nodes; | |
+ for (Node* n = processStart.get(); n && n != processEnd; n = n->nextSibling()) | |
+ nodes.append(n); | |
+ processNodes(action, nodes, commonRoot, fragment, ec); | |
} | |
if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContents) | |
@@ -898,6 +763,153 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception | |
return fragment.release(); | |
} | |
+static inline void deleteCharacterData(PassRefPtr<CharacterData> data, unsigned startOffset, unsigned endOffset, ExceptionCode& ec) | |
+{ | |
+ if (data->length() - endOffset) | |
+ data->deleteData(endOffset, data->length() - endOffset, ec); | |
+ if (startOffset) | |
+ data->deleteData(0, startOffset, ec); | |
+} | |
+ | |
+PassRefPtr<Node> Range::processContentsBetweenOffsets(ActionType action, PassRefPtr<DocumentFragment> fragment, | |
+ Node* container, unsigned startOffset, unsigned endOffset, ExceptionCode& ec) | |
+{ | |
+ ASSERT(container); | |
+ ASSERT(startOffset <= endOffset); | |
+ | |
+ // This switch statement must be consistent with that of lengthOfContentsInNode. | |
+ RefPtr<Node> result; | |
+ switch (container->nodeType()) { | |
+ case Node::TEXT_NODE: | |
+ case Node::CDATA_SECTION_NODE: | |
+ case Node::COMMENT_NODE: | |
+ ASSERT(endOffset <= static_cast<CharacterData*>(container)->length()); | |
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | |
+ RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(container->cloneNode(true)); | |
+ deleteCharacterData(c, startOffset, endOffset, ec); | |
+ if (fragment) { | |
+ result = fragment; | |
+ result->appendChild(c.release(), ec); | |
+ } else | |
+ result = c.release(); | |
+ } | |
+ if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) | |
+ static_cast<CharacterData*>(container)->deleteData(startOffset, endOffset - startOffset, ec); | |
+ break; | |
+ case Node::PROCESSING_INSTRUCTION_NODE: | |
+ ASSERT(endOffset <= static_cast<ProcessingInstruction*>(container)->data().length()); | |
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | |
+ RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(container->cloneNode(true)); | |
+ c->setData(c->data().substring(startOffset, endOffset - startOffset), ec); | |
+ if (fragment) { | |
+ result = fragment; | |
+ result->appendChild(c.release(), ec); | |
+ } else | |
+ result = c.release(); | |
+ } | |
+ if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | |
+ ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(container); | |
+ String data(pi->data()); | |
+ data.remove(startOffset, endOffset - startOffset); | |
+ pi->setData(data, ec); | |
+ } | |
+ break; | |
+ case Node::ELEMENT_NODE: | |
+ case Node::ATTRIBUTE_NODE: | |
+ case Node::ENTITY_REFERENCE_NODE: | |
+ case Node::ENTITY_NODE: | |
+ case Node::DOCUMENT_NODE: | |
+ case Node::DOCUMENT_TYPE_NODE: | |
+ case Node::DOCUMENT_FRAGMENT_NODE: | |
+ case Node::NOTATION_NODE: | |
+ case Node::XPATH_NAMESPACE_NODE: | |
+ // FIXME: Should we assert that some nodes never appear here? | |
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | |
+ if (fragment) | |
+ result = fragment; | |
+ else | |
+ result = container->cloneNode(false); | |
+ } | |
+ | |
+ Node* n = container->firstChild(); | |
+ Vector<RefPtr<Node> > nodes; | |
+ for (unsigned i = startOffset; n && i; i--) | |
+ n = n->nextSibling(); | |
+ for (unsigned i = startOffset; n && i < endOffset; i++, n = n->nextSibling()) | |
+ nodes.append(n); | |
+ | |
+ processNodes(action, nodes, container, result, ec); | |
+ break; | |
+ } | |
+ | |
+ return result.release(); | |
+} | |
+ | |
+void Range::processNodes(ActionType action, Vector<RefPtr<Node> >& nodes, PassRefPtr<Node> oldContainer, PassRefPtr<Node> newContainer, ExceptionCode& ec) | |
+{ | |
+ for (unsigned i = 0; i < nodes.size(); i++) { | |
+ switch (action) { | |
+ case DELETE_CONTENTS: | |
+ oldContainer->removeChild(nodes[i].get(), ec); | |
+ break; | |
+ case EXTRACT_CONTENTS: | |
+ newContainer->appendChild(nodes[i].release(), ec); // will remove n from its parent | |
+ break; | |
+ case CLONE_CONTENTS: | |
+ newContainer->appendChild(nodes[i]->cloneNode(true), ec); | |
+ break; | |
+ } | |
+ } | |
+} | |
+ | |
+PassRefPtr<Node> Range::processAncestorsAndTheirSiblings(ActionType action, Node* container, ContentsProcessDirection direction, PassRefPtr<Node> passedClonedContainer, Node* commonRoot, ExceptionCode& ec) | |
+{ | |
+ RefPtr<Node> clonedContainer = passedClonedContainer; | |
+ Vector<RefPtr<Node> > ancestors; | |
+ for (Node* n = container->parentNode(); n && n != commonRoot; n = n->parentNode()) | |
+ ancestors.append(n); | |
+ | |
+ RefPtr<Node> firstChildInAncestorToProcess = direction == ProcessContentsForward ? container->nextSibling() : container->previousSibling(); | |
+ for (Vector<RefPtr<Node> >::const_iterator it = ancestors.begin(); it != ancestors.end(); ++it) { | |
+ RefPtr<Node> ancestor = *it; | |
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | |
+ if (RefPtr<Node> clonedAncestor = ancestor->cloneNode(false)) { // Might have been removed already during mutation event. | |
+ clonedAncestor->appendChild(clonedContainer, ec); | |
+ clonedContainer = clonedAncestor; | |
+ } | |
+ } | |
+ | |
+ // Copy siblings of an ancestor of start/end containers | |
+ // FIXME: This assertion may fail if DOM is modified during mutation event | |
+ // FIXME: Share code with Range::processNodes | |
+ ASSERT(!firstChildInAncestorToProcess || firstChildInAncestorToProcess->parentNode() == ancestor); | |
+ RefPtr<Node> next; | |
+ for (Node* child = firstChildInAncestorToProcess.get(); child; child = next.get()) { | |
+ next = direction == ProcessContentsForward ? child->nextSibling() : child->previousSibling(); | |
+ switch (action) { | |
+ case DELETE_CONTENTS: | |
+ ancestor->removeChild(child, ec); | |
+ break; | |
+ case EXTRACT_CONTENTS: // will remove child from ancestor | |
+ if (direction == ProcessContentsForward) | |
+ clonedContainer->appendChild(child, ec); | |
+ else | |
+ clonedContainer->insertBefore(child, clonedContainer->firstChild(), ec); | |
+ break; | |
+ case CLONE_CONTENTS: | |
+ if (direction == ProcessContentsForward) | |
+ clonedContainer->appendChild(child->cloneNode(true), ec); | |
+ else | |
+ clonedContainer->insertBefore(child->cloneNode(true), clonedContainer->firstChild(), ec); | |
+ break; | |
+ } | |
+ } | |
+ firstChildInAncestorToProcess = direction == ProcessContentsForward ? ancestor->nextSibling() : ancestor->previousSibling(); | |
+ } | |
+ | |
+ return clonedContainer.release(); | |
+} | |
+ | |
PassRefPtr<DocumentFragment> Range::extractContents(ExceptionCode& ec) | |
{ | |
checkDeleteExtract(ec); | |
@@ -1024,7 +1036,7 @@ void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionCode& ec) | |
// This special case doesn't seem to match the DOM specification, but it's currently required | |
// to pass Acid3. We might later decide to remove this. | |
- if (collapsed) | |
+ if (collapsed && numNewChildren) | |
m_end.set(m_start.container(), startOffset + numNewChildren, lastChild.get()); | |
} | |
} | |
@@ -1334,6 +1346,9 @@ void Range::selectNode(Node* refNode, ExceptionCode& ec) | |
return; | |
} | |
+ if (m_ownerDocument != refNode->document()) | |
+ setDocument(refNode->document()); | |
+ | |
ec = 0; | |
setStartBefore(refNode, ec); | |
if (ec) | |
@@ -1376,6 +1391,9 @@ void Range::selectNodeContents(Node* refNode, ExceptionCode& ec) | |
} | |
} | |
+ if (m_ownerDocument != refNode->document()) | |
+ setDocument(refNode->document()); | |
+ | |
m_start.setToStartOfNode(refNode); | |
m_end.setToEndOfNode(refNode); | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Range.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Range.h | |
index 946095e..958e536 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Range.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Range.h | |
@@ -140,6 +140,8 @@ private: | |
Range(PassRefPtr<Document>); | |
Range(PassRefPtr<Document>, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset); | |
+ void setDocument(Document*); | |
+ | |
Node* checkNodeWOffset(Node*, int offset, ExceptionCode&) const; | |
void checkNodeBA(Node*, ExceptionCode&) const; | |
void checkDeleteExtract(ExceptionCode&); | |
@@ -149,6 +151,14 @@ private: | |
enum ActionType { DELETE_CONTENTS, EXTRACT_CONTENTS, CLONE_CONTENTS }; | |
PassRefPtr<DocumentFragment> processContents(ActionType, ExceptionCode&); | |
+ PassRefPtr<Node> processContentsBetweenOffsets(ActionType action, PassRefPtr<DocumentFragment> fragment, Node* container, unsigned startOffset, unsigned endOffset, ExceptionCode& ec); | |
+ void processNodes(ActionType action, Vector<RefPtr<Node> >& nodes, PassRefPtr<Node> oldContainer, PassRefPtr<Node> newContainer, ExceptionCode& ec); | |
+#if !PLATFORM(WKC) | |
+ enum ContentsProcessDirection { ProcessContentsForward, ProcessContentsBackward }; | |
+#else | |
+ enum ContentsProcessDirection { ProcessContentsForward, ProcessContentsBackward, ContentsProcessDirections=0x7fffffff }; | |
+#endif | |
+ PassRefPtr<Node> processAncestorsAndTheirSiblings(ActionType action, Node* container, ContentsProcessDirection direction, PassRefPtr<Node> passedClonedContainer, Node* commonRoot, ExceptionCode& ec); | |
void getBorderAndTextQuads(Vector<FloatQuad>&) const; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/RangeBoundaryPoint.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/RangeBoundaryPoint.h | |
index 1bbbe1a..2e91843 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/RangeBoundaryPoint.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/RangeBoundaryPoint.h | |
@@ -59,7 +59,7 @@ private: | |
RefPtr<Node> m_containerNode; | |
mutable int m_offsetInContainer; | |
- Node* m_childBeforeBoundary; | |
+ RefPtr<Node> m_childBeforeBoundary; | |
}; | |
inline RangeBoundaryPoint::RangeBoundaryPoint(PassRefPtr<Node> container) | |
@@ -77,7 +77,7 @@ inline Node* RangeBoundaryPoint::container() const | |
inline Node* RangeBoundaryPoint::childBefore() const | |
{ | |
- return m_childBeforeBoundary; | |
+ return m_childBeforeBoundary.get(); | |
} | |
inline void RangeBoundaryPoint::ensureOffsetIsValid() const | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/ScriptElement.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/ScriptElement.cpp | |
index 78eb667..c04e978 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/ScriptElement.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/ScriptElement.cpp | |
@@ -155,19 +155,20 @@ ScriptElementData::~ScriptElementData() | |
void ScriptElementData::requestScript(const String& sourceUrl) | |
{ | |
- Document* document = m_element->document(); | |
- | |
// FIXME: Eventually we'd like to evaluate scripts which are inserted into a | |
// viewless document but this'll do for now. | |
// See http://bugs.webkit.org/show_bug.cgi?id=5727 | |
- if (!document->frame()) | |
+ if (!m_element->document()->frame()) | |
return; | |
+ RefPtr<Document> originalDocument = m_element->document(); | |
if (!m_element->dispatchBeforeLoadEvent(sourceUrl)) | |
return; | |
+ if (!m_element->inDocument() || m_element->document() != originalDocument) | |
+ return; | |
ASSERT(!m_cachedScript); | |
- m_cachedScript = document->docLoader()->requestScript(sourceUrl, scriptCharset()); | |
+ m_cachedScript = m_element->document()->docLoader()->requestScript(sourceUrl, scriptCharset()); | |
m_requested = true; | |
// m_createdByParser is never reset - always resied at the initial value set while parsing. | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/ScriptExecutionContext.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/ScriptExecutionContext.cpp | |
index bc71084..62e4aeb 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/ScriptExecutionContext.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/ScriptExecutionContext.cpp | |
@@ -20,7 +20,7 @@ | |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
* | |
*/ | |
@@ -159,6 +159,9 @@ void ScriptExecutionContext::stopActiveDOMObjects() | |
ASSERT(iter->first->scriptExecutionContext() == this); | |
iter->first->stop(); | |
} | |
+ | |
+ // Also close MessagePorts. If they were ActiveDOMObjects (they could be) then they could be stopped instead. | |
+ closeMessagePorts(); | |
} | |
void ScriptExecutionContext::createdActiveDOMObject(ActiveDOMObject* object, void* upcastPointer) | |
@@ -174,6 +177,14 @@ void ScriptExecutionContext::destroyedActiveDOMObject(ActiveDOMObject* object) | |
m_activeDOMObjects.remove(object); | |
} | |
+void ScriptExecutionContext::closeMessagePorts() { | |
+ HashSet<MessagePort*>::iterator messagePortsEnd = m_messagePorts.end(); | |
+ for (HashSet<MessagePort*>::iterator iter = m_messagePorts.begin(); iter != messagePortsEnd; ++iter) { | |
+ ASSERT((*iter)->scriptExecutionContext() == this); | |
+ (*iter)->close(); | |
+ } | |
+} | |
+ | |
void ScriptExecutionContext::setSecurityOrigin(PassRefPtr<SecurityOrigin> securityOrigin) | |
{ | |
m_securityOrigin = securityOrigin; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/ScriptExecutionContext.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/ScriptExecutionContext.h | |
index cf332c3..d4bc745 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/ScriptExecutionContext.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/ScriptExecutionContext.h | |
@@ -20,7 +20,7 @@ | |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
* | |
*/ | |
@@ -119,6 +119,8 @@ namespace WebCore { | |
virtual const KURL& virtualURL() const = 0; | |
virtual KURL virtualCompleteURL(const String&) const = 0; | |
+ void closeMessagePorts(); | |
+ | |
RefPtr<SecurityOrigin> m_securityOrigin; | |
HashSet<MessagePort*> m_messagePorts; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/SelectElement.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/SelectElement.cpp | |
index 2d00350..ad49228 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/SelectElement.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/SelectElement.cpp | |
@@ -82,6 +82,8 @@ void SelectElement::selectAll(SelectElementData& data, Element* element) | |
data.setActiveSelectionState(true); | |
setActiveSelectionAnchorIndex(data, element, nextSelectableListIndex(data, element, -1)); | |
setActiveSelectionEndIndex(data, previousSelectableListIndex(data, element, -1)); | |
+ if (data.activeSelectionAnchorIndex() < 0) | |
+ return; | |
updateListBoxSelection(data, element, false); | |
listBoxOnChange(data, element); | |
@@ -670,6 +672,10 @@ void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element* | |
if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) { | |
element->focus(); | |
+ // Calling focus() may remove or change our renderer, in which case we don't want to handle the event further. | |
+ if (!element->renderer() || !element->renderer()->isListBox()) | |
+ return; | |
+ | |
// Convert to coords relative to the list box if needed. | |
MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); | |
IntPoint localOffset = roundedIntPoint(element->renderer()->absoluteToLocal(mouseEvent->absoluteLocation(), false, true)); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Tokenizer.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Tokenizer.h | |
index bed3b14..bda1720 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/Tokenizer.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/Tokenizer.h | |
@@ -24,14 +24,18 @@ | |
#ifndef Tokenizer_h | |
#define Tokenizer_h | |
+#include <wtf/RefCounted.h> | |
+ | |
namespace WebCore { | |
class SegmentedString; | |
class XSSAuditor; | |
- class Tokenizer : public Noncopyable { | |
+ class Tokenizer : public RefCounted<Tokenizer> { | |
public: | |
- virtual ~Tokenizer() { } | |
+ virtual ~Tokenizer() | |
+ { | |
+ } | |
// Script output must be prepended, while new data | |
// received during executing a script must be appended, hence the | |
@@ -62,10 +66,9 @@ namespace WebCore { | |
XSSAuditor* xssAuditor() const { return m_XSSAuditor; } | |
void setXSSAuditor(XSSAuditor* auditor) { m_XSSAuditor = auditor; } | |
-#if PLATFORM(WKC) | |
- // cf. webkit.org trunk r65692 | |
- virtual bool detach() { return true; } | |
-#endif | |
+ virtual void detach() | |
+ { | |
+ } | |
protected: | |
Tokenizer(bool viewSourceMode = false) | |
@@ -78,6 +81,7 @@ namespace WebCore { | |
// The tokenizer has buffers, so parsing may continue even after | |
// it stops receiving data. We use m_parserStopped to stop the tokenizer | |
// even when it has buffered data. | |
+ // FIXME: m_document = 0 could be changed to mean "parser stopped". | |
bool m_parserStopped; | |
bool m_inViewSourceMode; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/XMLTokenizer.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/XMLTokenizer.cpp | |
index 25a9aae..47e1427 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/XMLTokenizer.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/XMLTokenizer.cpp | |
@@ -204,19 +204,15 @@ void XMLTokenizer::exitText() | |
popCurrentNode(); | |
} | |
-#if PLATFORM(WKC) | |
-// cf. webkit.org trunk r65958 | |
-bool XMLTokenizer::detach() | |
+void XMLTokenizer::detach() | |
{ | |
clearCurrentNodeStack(); | |
if (m_refCount > 0) { | |
// An unexpected error occurred. | |
wkcMemoryNotifyNoMemoryPeer(0x7fffffff, false); | |
- return false; | |
+ return; | |
} | |
- return true; | |
} | |
-#endif | |
void XMLTokenizer::end() | |
{ | |
@@ -245,6 +241,11 @@ void XMLTokenizer::end() | |
void XMLTokenizer::finish() | |
{ | |
+ // FIXME: We should ASSERT(!m_parserStopped) here, since it does not | |
+ // makes sense to call any methods on DocumentParser once it's been stopped. | |
+ // However, FrameLoader::stop calls Document::finishParsing unconditionally | |
+ // which in turn calls m_parser->finish(). | |
+ | |
if (m_parserPaused) | |
m_finishCalled = true; | |
else | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/XMLTokenizer.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/XMLTokenizer.h | |
index bdb8505..40452f1 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/XMLTokenizer.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/XMLTokenizer.h | |
@@ -72,8 +72,14 @@ namespace WebCore { | |
class XMLTokenizer : public Tokenizer, public CachedResourceClient { | |
public: | |
- XMLTokenizer(Document*, FrameView* = 0); | |
- XMLTokenizer(DocumentFragment*, Element*); | |
+ static PassRefPtr<XMLTokenizer> create(Document* document, FrameView* view) | |
+ { | |
+ return adoptRef(new XMLTokenizer(document, view)); | |
+ } | |
+ static PassRefPtr<XMLTokenizer> create(DocumentFragment* fragment, Element* element) | |
+ { | |
+ return adoptRef(new XMLTokenizer(fragment, element)); | |
+ } | |
~XMLTokenizer(); | |
enum ErrorType { warning, nonFatal, fatal }; | |
@@ -84,10 +90,7 @@ namespace WebCore { | |
virtual bool isWaitingForScripts() const; | |
virtual void stopParsing(); | |
-#if PLATFORM(WKC) | |
- // cf. webkit.org trunk r65958 | |
- virtual bool detach(); | |
-#endif | |
+ virtual void detach(); | |
void end(); | |
@@ -146,6 +149,9 @@ public: | |
private: | |
friend bool parseXMLDocumentFragment(const String& chunk, DocumentFragment* fragment, Element* parent); | |
+ XMLTokenizer(Document*, FrameView* = 0); | |
+ XMLTokenizer(DocumentFragment*, Element*); | |
+ | |
void initializeParserContext(const char* chunk = 0); | |
void pushCurrentNode(Node*); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/XMLTokenizerLibxml2.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/XMLTokenizerLibxml2.cpp | |
index 55a20ed..a2c3e41 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/dom/XMLTokenizerLibxml2.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/dom/XMLTokenizerLibxml2.cpp | |
@@ -883,6 +883,10 @@ void XMLTokenizer::endElementNs() | |
exitText(); | |
+#if PLATFORM(WKC) | |
+ if (!m_currentNode) | |
+ return; | |
+#endif | |
Node* n = m_currentNode; | |
n->finishParsingChildren(); | |
@@ -1462,27 +1466,24 @@ bool parseXMLDocumentFragment(const String& chunk, DocumentFragment* fragment, E | |
if (!chunk.length()) | |
return true; | |
- XMLTokenizer tokenizer(fragment, parent); | |
+ RefPtr<XMLTokenizer> tokenizer = XMLTokenizer::create(fragment, parent); | |
CString chunkAsUtf8 = chunk.utf8(); | |
- tokenizer.initializeParserContext(chunkAsUtf8.data()); | |
+ tokenizer->initializeParserContext(chunkAsUtf8.data()); | |
- xmlParseContent(tokenizer.context()); | |
+ xmlParseContent(tokenizer->context()); | |
- tokenizer.endDocument(); | |
+ tokenizer->endDocument(); | |
// Check if all the chunk has been processed. | |
- long bytesProcessed = xmlByteConsumed(tokenizer.context()); | |
+ long bytesProcessed = xmlByteConsumed(tokenizer->context()); | |
if (bytesProcessed == -1 || ((unsigned long)bytesProcessed) != chunkAsUtf8.length()) | |
return false; | |
-#if PLATFORM(WKC) | |
- // cf. webkit.org trunk r65692 | |
- tokenizer.detach(); | |
-#endif | |
+ tokenizer->detach(); | |
// No error if the chunk is well formed or it is not but we have no error. | |
- return tokenizer.context()->wellFormed || xmlCtxtGetLastError(tokenizer.context()) == 0; | |
+ return tokenizer->context()->wellFormed || !xmlCtxtGetLastError(tokenizer->context()); | |
} | |
// -------------------------------- | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/CompositeEditCommand.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/CompositeEditCommand.cpp | |
index 4c858d0..897af0a 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/CompositeEditCommand.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/CompositeEditCommand.cpp | |
@@ -799,10 +799,10 @@ void CompositeEditCommand::cloneParagraphUnderNewElement(Position& start, Positi | |
// Deleting a paragraph will leave a placeholder. Remove it (and prune | |
// empty or unrendered parents). | |
-void CompositeEditCommand::cleanupAfterDeletion() | |
+void CompositeEditCommand::cleanupAfterDeletion(VisiblePosition destination) | |
{ | |
VisiblePosition caretAfterDelete = endingSelection().visibleStart(); | |
- if (isStartOfParagraph(caretAfterDelete) && isEndOfParagraph(caretAfterDelete)) { | |
+ if (caretAfterDelete != destination && isStartOfParagraph(caretAfterDelete) && isEndOfParagraph(caretAfterDelete)) { | |
// Note: We want the rightmost candidate. | |
Position position = caretAfterDelete.deepEquivalent().downstream(); | |
Node* node = position.node(); | |
@@ -813,9 +813,15 @@ void CompositeEditCommand::cleanupAfterDeletion() | |
// doesn't require a placeholder to prop itself open (like a bordered | |
// div or an li), remove it during the move (the list removal code | |
// expects this behavior). | |
- else if (isBlock(node)) | |
+ else if (isBlock(node)) { | |
+ // If caret position after deletion and destination position coincides, | |
+ // node should not be removed. | |
+ if (!position.rendersInDifferentPosition(destination.deepEquivalent())) { | |
+ prune(node); | |
+ return; | |
+ } | |
removeNodeAndPruneAncestors(node); | |
- else if (lineBreakExistsAtPosition(position)) { | |
+ } else if (lineBreakExistsAtPosition(position)) { | |
// There is a preserved '\n' at caretAfterDelete. | |
// We can safely assume this is a text node. | |
Text* textNode = static_cast<Text*>(node); | |
@@ -949,7 +955,7 @@ void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap | |
ASSERT(destination.deepEquivalent().node()->inDocument()); | |
- cleanupAfterDeletion(); | |
+ cleanupAfterDeletion(destination); | |
// Add a br if pruning an empty block level element caused a collapse. For example: | |
// foo^ | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/CompositeEditCommand.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/CompositeEditCommand.h | |
index 0cceaaa..9c80ca8 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/CompositeEditCommand.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/CompositeEditCommand.h | |
@@ -104,7 +104,7 @@ protected: | |
void moveParagraphs(const VisiblePosition&, const VisiblePosition&, const VisiblePosition&, bool preserveSelection = false, bool preserveStyle = true); | |
void moveParagraphWithClones(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, Element* blockElement, Node* outerNode); | |
void cloneParagraphUnderNewElement(Position& start, Position& end, Node* outerNode, Element* blockElement); | |
- void cleanupAfterDeletion(); | |
+ void cleanupAfterDeletion(VisiblePosition destination = VisiblePosition()); | |
bool breakOutOfEmptyListItem(); | |
bool breakOutOfEmptyMailBlockquotedParagraph(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/DeleteButtonController.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/DeleteButtonController.cpp | |
index c5a4a7d..2aadc3b 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/DeleteButtonController.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/DeleteButtonController.cpp | |
@@ -112,8 +112,12 @@ static bool isDeletableElement(const Node* node) | |
return false; | |
// Allow blocks that have background images | |
- if (style->hasBackgroundImage() && style->backgroundImage()->canRender(1.0f)) | |
- return true; | |
+ if (style->hasBackgroundImage()) { | |
+ for (const FillLayer* background = style->backgroundLayers(); background; background = background->next()) { | |
+ if (background->image() && background->image()->canRender(1)) | |
+ return true; | |
+ } | |
+ } | |
// Allow blocks with a minimum number of non-transparent borders | |
unsigned visibleBorders = style->borderTop().isVisible() + style->borderBottom().isVisible() + style->borderLeft().isVisible() + style->borderRight().isVisible(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/SelectionController.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/SelectionController.cpp | |
index 8d24eae..4fd6287 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/SelectionController.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/SelectionController.cpp | |
@@ -1,5 +1,5 @@ | |
/* | |
- * Copyright (C) 2004, 2008 Apple Inc. All rights reserved. | |
+ * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved. | |
* Copyright (c) 2011 ACCESS CO., LTD. All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
@@ -71,6 +71,7 @@ SelectionController::SelectionController(Frame* frame, bool isDragCaretControlle | |
, m_isDragCaretController(isDragCaretController) | |
, m_isCaretBlinkingSuspended(false) | |
, m_focused(frame && frame->page() && frame->page()->focusController()->focusedFrame() == frame) | |
+ , m_needsDisplayUpdate(false) | |
{ | |
} | |
@@ -146,7 +147,8 @@ void SelectionController::setSelection(const VisibleSelection& s, bool closeTypi | |
if (!s.isNone()) | |
m_frame->setFocusedNodeIfNeeded(); | |
- m_frame->selectionLayoutChanged(); | |
+ setNeedsDisplayUpdate(); | |
+ | |
// Always clear the x position used for vertical arrow navigation. | |
// It will be restored by the vertical arrow navigation code if necessary. | |
m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation; | |
@@ -1305,6 +1307,20 @@ bool SelectionController::isFocusedAndActive() const | |
return m_focused && m_frame->page() && m_frame->page()->focusController()->isActive(); | |
} | |
+void SelectionController::setNeedsDisplayUpdate(bool needsUpdate) | |
+{ | |
+ if (m_needsDisplayUpdate == needsUpdate) | |
+ return; | |
+ m_needsDisplayUpdate = needsUpdate; | |
+ | |
+ if (!m_needsDisplayUpdate) | |
+ return; | |
+ FrameView* view = m_frame->view(); | |
+ if (!view) | |
+ return; | |
+ view->scheduleRelayout(); | |
+} | |
+ | |
#ifndef NDEBUG | |
void SelectionController::formatForDebugger(char* buffer, unsigned length) const | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/SelectionController.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/SelectionController.h | |
index d03df52..05ee1dc 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/SelectionController.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/SelectionController.h | |
@@ -1,5 +1,5 @@ | |
/* | |
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved. | |
+ * Copyright (C) 2004, 2009, 2010 Apple Inc. All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
@@ -124,6 +124,10 @@ public: | |
bool isFocusedAndActive() const; | |
void pageActivationChanged(); | |
+ // Selection display machinery | |
+ void setNeedsDisplayUpdate(bool = true); | |
+ bool needsDisplayUpdate() const { return m_needsDisplayUpdate; } | |
+ | |
#ifndef NDEBUG | |
void formatForDebugger(char* buffer, unsigned length) const; | |
void showTreeForThis() const; | |
@@ -175,6 +179,7 @@ private: | |
bool m_isCaretBlinkingSuspended : 1; | |
bool m_focused : 1; | |
+ bool m_needsDisplayUpdate : 1; | |
}; | |
inline bool operator==(const SelectionController& a, const SelectionController& b) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/TextIterator.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/TextIterator.cpp | |
index 886b858..b3b397c 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/TextIterator.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/TextIterator.cpp | |
@@ -1951,6 +1951,9 @@ tryAgain: | |
PassRefPtr<Range> findPlainText(const Range* range, const String& target, bool forward, bool caseSensitive) | |
{ | |
+ // CharacterIterator requires renderers to be up-to-date | |
+ range->ownerDocument()->updateLayout(); | |
+ | |
// First, find the text. | |
size_t matchStart; | |
size_t matchLength; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/VisiblePosition.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/VisiblePosition.cpp | |
index 2db6d31..99167ef 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/VisiblePosition.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/VisiblePosition.cpp | |
@@ -462,6 +462,8 @@ Position VisiblePosition::canonicalPosition(const Position& position) | |
if (!node) | |
return Position(); | |
+ ASSERT(node->document()); | |
+ | |
node->document()->updateLayoutIgnorePendingStylesheets(); | |
Position candidate = position.upstream(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/visible_units.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/visible_units.cpp | |
index 84ace83..ed1b550 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/editing/visible_units.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/editing/visible_units.cpp | |
@@ -235,17 +235,20 @@ static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunc | |
if (it.atEnd() && next == string.size()) { | |
pos = it.range()->startPosition(); | |
- } else if (next != prefixLength) { | |
+ } else if (next != prefixLength && next!=0xffffffff) { | |
// Use the character iterator to translate the next value into a DOM position. | |
CharacterIterator charIt(searchRange.get(), true); | |
charIt.advance(next - prefixLength - 1); | |
- pos = charIt.range()->endPosition(); | |
+ RefPtr<Range> characterRange = charIt.range(); | |
+ pos = characterRange->endPosition(); | |
if (*charIt.characters() == '\n') { | |
// FIXME: workaround for collapsed range (where only start position is correct) emitted for some emitted newlines (see rdar://5192593) | |
VisiblePosition visPos = VisiblePosition(pos); | |
- if (visPos == VisiblePosition(charIt.range()->startPosition())) | |
- pos = visPos.next(true).deepEquivalent(); | |
+ if (visPos == VisiblePosition(charIt.range()->startPosition())) { | |
+ charIt.advance(1); | |
+ pos = charIt.range()->startPosition(); | |
+ } | |
} | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLAnchorElement.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLAnchorElement.cpp | |
index 1d5d569..58c9ea3 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLAnchorElement.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLAnchorElement.cpp | |
@@ -497,19 +497,8 @@ String HTMLAnchorElement::protocol() const | |
void HTMLAnchorElement::setProtocol(const String& value) | |
{ | |
- int separator = value.find(':'); | |
- | |
- if (!separator) | |
- return; | |
- if (value.isEmpty()) | |
- return; | |
- | |
KURL url = href(); | |
- // Following Firefox 3.5.2 which removes anything after the first ":" | |
- String newProtocol = value.substring(0, separator); | |
- if (!isValidProtocol(newProtocol)) | |
- return; | |
- url.setProtocol(newProtocol); | |
+ (void)url.setProtocol(value); | |
setHref(url.string()); | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLDocument.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLDocument.cpp | |
index 0d1cb19..4d19124 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLDocument.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLDocument.cpp | |
@@ -281,7 +281,7 @@ void HTMLDocument::releaseEvents() | |
{ | |
} | |
-Tokenizer *HTMLDocument::createTokenizer() | |
+PassRefPtr<Tokenizer> HTMLDocument::createTokenizer() | |
{ | |
bool reportErrors = false; | |
#if ENABLE(INSPECTOR) | |
@@ -289,7 +289,7 @@ Tokenizer *HTMLDocument::createTokenizer() | |
reportErrors = page->inspectorController()->windowVisible(); | |
#endif | |
- return new HTMLTokenizer(this, reportErrors); | |
+ return HTMLTokenizer::create(this, reportErrors); | |
} | |
// -------------------------------------------------------------------------- | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLDocument.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLDocument.h | |
index 4b14d0c..02156d6 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLDocument.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLDocument.h | |
@@ -89,7 +89,7 @@ private: | |
virtual bool isHTMLDocument() const { return true; } | |
virtual bool isFrameSet() const; | |
- virtual Tokenizer* createTokenizer(); | |
+ virtual PassRefPtr<Tokenizer> createTokenizer(); | |
virtual void determineParseMode(); | |
HashCountedSet<AtomicStringImpl*> m_namedItemCounts; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLFrameElementBase.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLFrameElementBase.cpp | |
index 9551b6e..2b37d6f 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLFrameElementBase.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLFrameElementBase.cpp | |
@@ -57,6 +57,9 @@ HTMLFrameElementBase::HTMLFrameElementBase(const QualifiedName& tagName, Documen | |
bool HTMLFrameElementBase::isURLAllowed() const | |
{ | |
+ if (document() && document()->page() && document()->page()->frameCount() >= 200) | |
+ return false; | |
+ | |
if (m_URL.isEmpty()) | |
return true; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLFrameSetElement.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLFrameSetElement.cpp | |
index 6c1630b..67ba1a0 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLFrameSetElement.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLFrameSetElement.cpp | |
@@ -198,7 +198,7 @@ void HTMLFrameSetElement::attach() | |
void HTMLFrameSetElement::defaultEventHandler(Event* evt) | |
{ | |
- if (evt->isMouseEvent() && !noresize && renderer()) { | |
+ if (evt->isMouseEvent() && !noresize && renderer() && renderer()->isFrameSet()) { | |
if (toRenderFrameSet(renderer())->userResize(static_cast<MouseEvent*>(evt))) { | |
evt->setDefaultHandled(); | |
return; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLLinkElement.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLLinkElement.cpp | |
index 66aa6c8..d896aaf 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLLinkElement.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLLinkElement.cpp | |
@@ -2,7 +2,7 @@ | |
* Copyright (C) 1999 Lars Knoll (knoll@kde.org) | |
* (C) 1999 Antti Koivisto (koivisto@kde.org) | |
* (C) 2001 Dirk Mueller (mueller@kde.org) | |
- * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | |
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. | |
* Copyright (C) 2009 Rob Buis (rwlbuis@gmail.com) | |
* Copyright (c) 2010 ACCESS CO., LTD. All rights reserved. | |
* | |
@@ -57,6 +57,7 @@ HTMLLinkElement::HTMLLinkElement(const QualifiedName& qName, Document *doc, bool | |
, m_isIcon(false) | |
, m_isDNSPrefetch(false) | |
, m_createdByParser(createdByParser) | |
+ , m_shouldProcessAfterAttach(false) | |
{ | |
ASSERT(hasTagName(linkTag)); | |
} | |
@@ -235,11 +236,23 @@ void HTMLLinkElement::process() | |
} | |
} | |
+void HTMLLinkElement::processCallback(Node* node) | |
+{ | |
+ ASSERT_ARG(node, node && node->hasTagName(linkTag)); | |
+ static_cast<HTMLLinkElement*>(node)->process(); | |
+} | |
+ | |
void HTMLLinkElement::insertedIntoDocument() | |
{ | |
HTMLElement::insertedIntoDocument(); | |
document()->addStyleSheetCandidateNode(this, m_createdByParser); | |
- process(); | |
+ | |
+ // Since processing a stylesheet link causes a beforeload event | |
+ // to fire, it is possible for JavaScript to remove the element in the midst | |
+ // of it being inserted into the DOM, which can lead to assertion failures | |
+ // and crashes. Avoid this by postponing the beforeload/load until after | |
+ // attach. | |
+ m_shouldProcessAfterAttach = true; | |
} | |
void HTMLLinkElement::removedFromDocument() | |
@@ -251,8 +264,19 @@ void HTMLLinkElement::removedFromDocument() | |
// FIXME: It's terrible to do a synchronous update of the style selector just because a <style> or <link> element got removed. | |
if (document()->renderer()) | |
document()->updateStyleSelector(); | |
+ | |
+ m_shouldProcessAfterAttach = false; | |
} | |
+void HTMLLinkElement::attach() | |
+{ | |
+ if (m_shouldProcessAfterAttach) { | |
+ m_shouldProcessAfterAttach = false; | |
+ queuePostAttachCallback(&HTMLLinkElement::processCallback, this); | |
+ } | |
+ | |
+ HTMLElement::attach(); | |
+} | |
void HTMLLinkElement::finishParsingChildren() | |
{ | |
m_createdByParser = false; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLLinkElement.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLLinkElement.h | |
index ad96e99..7813b14 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLLinkElement.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLLinkElement.h | |
@@ -75,6 +75,7 @@ public: | |
virtual void parseMappedAttribute(MappedAttribute*); | |
void process(); | |
+ static void processCallback(Node*); | |
virtual void insertedIntoDocument(); | |
virtual void removedFromDocument(); | |
@@ -93,6 +94,9 @@ public: | |
bool isDisabled() const { return m_disabledState == 2; } | |
bool isEnabledViaScript() const { return m_disabledState == 1; } | |
bool isIcon() const { return m_isIcon; } | |
+ | |
+ virtual void attach(); | |
+ virtual bool canLazyAttach() { return false; } | |
int disabledState() { return m_disabledState; } | |
void setDisabledState(bool _disabled); | |
@@ -123,6 +127,7 @@ protected: | |
bool m_isIcon; | |
bool m_isDNSPrefetch; | |
bool m_createdByParser; | |
+ bool m_shouldProcessAfterAttach; | |
}; | |
} //namespace | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLObjectElement.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLObjectElement.cpp | |
index 7a6a14d..be05d34 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLObjectElement.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLObjectElement.cpp | |
@@ -246,6 +246,9 @@ void HTMLObjectElement::renderFallbackContent() | |
if (m_useFallbackContent) | |
return; | |
+ if (!inDocument()) | |
+ return; | |
+ | |
// Before we give up and use fallback content, check to see if this is a MIME type issue. | |
if (m_imageLoader && m_imageLoader->image()) { | |
m_serviceType = m_imageLoader->image()->response().mimeType(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLParser.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLParser.cpp | |
index 3e686de..070e649 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLParser.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLParser.cpp | |
@@ -66,6 +66,7 @@ using namespace HTMLNames; | |
static const unsigned cMaxRedundantTagDepth = 20; | |
static const unsigned cResidualStyleMaxDepth = 200; | |
+static const unsigned cResidualStyleIterationLimit = 5; | |
static const int minBlockLevelTagPriority = 3; | |
@@ -125,6 +126,10 @@ struct HTMLStackElem : Noncopyable { | |
* | |
*/ | |
+#if PLATFORM(WKC) | |
+static Vector<HTMLParser*>* gValidParsers = 0; | |
+#endif | |
+ | |
HTMLParser::HTMLParser(HTMLDocument* doc, bool reportErrors) | |
: m_document(doc) | |
, m_current(doc) | |
@@ -141,6 +146,11 @@ HTMLParser::HTMLParser(HTMLDocument* doc, bool reportErrors) | |
, m_inStrayTableContent(0) | |
, m_parserQuirks(m_document->page() ? m_document->page()->chrome()->client()->createHTMLParserQuirks() : 0) | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!gValidParsers) | |
+ gValidParsers = new Vector<HTMLParser*>(); | |
+ gValidParsers->append(this); | |
+#endif | |
} | |
HTMLParser::HTMLParser(DocumentFragment* frag) | |
@@ -161,6 +171,11 @@ HTMLParser::HTMLParser(DocumentFragment* frag) | |
{ | |
if (frag) | |
frag->ref(); | |
+#if PLATFORM(WKC) | |
+ if (!gValidParsers) | |
+ gValidParsers = new Vector<HTMLParser*>(); | |
+ gValidParsers->append(this); | |
+#endif | |
} | |
HTMLParser::~HTMLParser() | |
@@ -168,6 +183,18 @@ HTMLParser::~HTMLParser() | |
freeBlock(); | |
if (m_didRefCurrent) | |
m_current->deref(); | |
+#if PLATFORM(WKC) | |
+ size_t pos = gValidParsers->find(this); | |
+ if (pos!=notFound) | |
+ gValidParsers->remove(pos); | |
+#endif | |
+} | |
+ | |
+void HTMLParser::detach() | |
+{ | |
+ // This call makes little sense in fragment mode, but for consistency | |
+ // HTMLParser expects detach() to always be called before it's destroyed. | |
+ m_document = 0; | |
} | |
void HTMLParser::reset() | |
@@ -575,6 +602,10 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName, | |
#endif | |
createHead(); | |
+#if PLATFORM(WKC) | |
+ if (gValidParsers->find(this)==notFound) | |
+ return false; | |
+#endif | |
popBlock(headTag); | |
e = new HTMLBodyElement(bodyTag, m_document); | |
startBody(); | |
@@ -1197,8 +1228,10 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem) | |
bool finished = false; | |
bool strayTableContent = elem->strayTableContent; | |
+ unsigned iterationCount = 0; | |
+ | |
m_handlingResidualStyleAcrossBlocks = true; | |
- while (!finished) { | |
+ while (!finished && (iterationCount++ < cResidualStyleIterationLimit)) { | |
// Find the outermost element that crosses over to a higher level. If there exists another higher-level | |
// element, we will do another pass, until we have corrected the innermost one. | |
ExceptionCode ec = 0; | |
@@ -1683,6 +1716,11 @@ void HTMLParser::createHead() | |
m_document->documentElement()->insertBefore(m_head.get(), body, ec); | |
if (ec) | |
m_head = 0; | |
+ | |
+#if PLATFORM(WKC) | |
+ if (gValidParsers->find(this)==notFound) | |
+ return; | |
+#endif | |
// If the body does not exist yet, then the <head> should be pushed as the current block. | |
if (m_head && !body) { | |
@@ -1739,7 +1777,7 @@ void HTMLParser::finished() | |
freeBlock(); | |
setCurrent(0); | |
- // Warning, this may delete the tokenizer and parser, so don't try to do anything else after this. | |
+ // Warning, this may detach the tokenizer and parser, so don't try to do anything else after this. | |
if (!m_isParsingFragment) | |
m_document->finishedParsing(); | |
} | |
@@ -1821,6 +1859,7 @@ void HTMLParser::resetVariables() | |
gHeaderTags = 0; | |
gResidualStyleTags = 0; | |
gUnaffectedTags = 0; | |
+ gValidParsers = 0; | |
} | |
#endif | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLParser.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLParser.h | |
index 1ec1055..f9f3f6b 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLParser.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLParser.h | |
@@ -56,6 +56,8 @@ public: | |
HTMLParser(DocumentFragment*); | |
virtual ~HTMLParser(); | |
+ void detach(); | |
+ | |
/** | |
* parses one token delivered by the tokenizer | |
*/ | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLSelectElement.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLSelectElement.cpp | |
index 2ca9f03..11e49d8 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLSelectElement.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLSelectElement.cpp | |
@@ -422,11 +422,21 @@ void HTMLSelectElement::setLength(unsigned newLen, ExceptionCode& ec) | |
} else { | |
const Vector<Element*>& items = listItems(); | |
+ // Removing children fires mutation events, which might mutate the DOM further, so we first copy out a list | |
+ // of elements that we intend to remove then attempt to remove them one at a time. | |
+ Vector<RefPtr<Element> > itemsToRemove; | |
size_t optionIndex = 0; | |
- for (size_t listIndex = 0; listIndex < items.size(); listIndex++) { | |
- if (items[listIndex]->hasLocalName(optionTag) && optionIndex++ >= newLen) { | |
- Element *item = items[listIndex]; | |
+ for (size_t i = 0; i < items.size(); ++i) { | |
+ Element* item = items[i]; | |
+ if (item->hasLocalName(optionTag) && optionIndex++ >= newLen) { | |
ASSERT(item->parentNode()); | |
+ itemsToRemove.append(item); | |
+ } | |
+ } | |
+ | |
+ for (size_t i = 0; i < itemsToRemove.size(); ++i) { | |
+ Element* item = itemsToRemove[i].get(); | |
+ if (item->parentNode()) { | |
item->parentNode()->removeChild(item, ec); | |
} | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLTextAreaElement.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLTextAreaElement.cpp | |
index e0bd8c5..3e1a5b0 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLTextAreaElement.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLTextAreaElement.cpp | |
@@ -184,6 +184,8 @@ bool HTMLTextAreaElement::appendFormData(FormDataList& encoding, bool) | |
if (name().isEmpty()) | |
return false; | |
+ document()->updateLayout(); | |
+ | |
// FIXME: It's not acceptable to ignore the HardWrap setting when there is no renderer. | |
// While we have no evidence this has ever been a practical problem, it would be best to fix it some day. | |
RenderTextControl* control = toRenderTextControl(renderer()); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLTokenizer.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLTokenizer.cpp | |
index 9363ddb..89a0db9 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLTokenizer.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLTokenizer.cpp | |
@@ -8,7 +8,7 @@ | |
Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | |
Copyright (C) 2005, 2006 Alexey Proskuryakov (ap@nypop.com) | |
Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) | |
- Copyright (c) 2011 ACCESS CO., LTD. All rights reserved. | |
+ Copyright (c) 2011, 2015 ACCESS CO., LTD. All rights reserved. | |
This library is free software; you can redistribute it and/or | |
modify it under the terms of the GNU Library General Public | |
@@ -155,6 +155,10 @@ inline void Token::addAttribute(AtomicString& attrName, const AtomicString& attr | |
attrName = emptyAtom; | |
} | |
+#if PLATFORM(WKC) | |
+static Vector<HTMLTokenizer*>* gValidInstances = 0; | |
+#endif | |
+ | |
// ---------------------------------------------------------------------------- | |
HTMLTokenizer::HTMLTokenizer(HTMLDocument* doc, bool reportErrors) | |
@@ -174,6 +178,11 @@ HTMLTokenizer::HTMLTokenizer(HTMLDocument* doc, bool reportErrors) | |
, m_inWrite(false) | |
, m_fragment(false) | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!gValidInstances) | |
+ gValidInstances = new Vector<HTMLTokenizer*>(); | |
+ gValidInstances->append(this); | |
+#endif | |
begin(); | |
} | |
@@ -194,6 +203,11 @@ HTMLTokenizer::HTMLTokenizer(HTMLViewSourceDocument* doc) | |
, m_inWrite(false) | |
, m_fragment(false) | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!gValidInstances) | |
+ gValidInstances = new Vector<HTMLTokenizer*>(); | |
+ gValidInstances->append(this); | |
+#endif | |
begin(); | |
} | |
@@ -213,9 +227,24 @@ HTMLTokenizer::HTMLTokenizer(DocumentFragment* frag) | |
, m_inWrite(false) | |
, m_fragment(true) | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!gValidInstances) | |
+ gValidInstances = new Vector<HTMLTokenizer*>(); | |
+ gValidInstances->append(this); | |
+#endif | |
begin(); | |
} | |
+void HTMLTokenizer::detach() | |
+{ | |
+ Tokenizer::detach(); | |
+ // FIXME: It seems wrong that we would have a preload scanner here. | |
+ // Yet during fast/dom/HTMLScriptElement/script-load-events.html we do. | |
+ m_preloadScanner.clear(); | |
+ m_timer.stop(); | |
+ m_pendingScripts.clear(); | |
+} | |
+ | |
void HTMLTokenizer::reset() | |
{ | |
ASSERT(m_executingScript == 0); | |
@@ -1631,6 +1660,8 @@ void HTMLTokenizer::write(const SegmentedString& str, bool appendData) | |
if (m_parserStopped) | |
return; | |
+ RefPtr<HTMLTokenizer> protect(this); | |
+ | |
SegmentedString source(str); | |
if (m_executingScript) | |
source.setExcludeLineNumbers(); | |
@@ -1853,6 +1884,8 @@ void HTMLTokenizer::timerFired(Timer<HTMLTokenizer>*) | |
void HTMLTokenizer::end() | |
{ | |
ASSERT(!m_timer.isActive()); | |
+ RefPtr<HTMLTokenizer> protect(this); | |
+ | |
m_timer.stop(); // Only helps if assertion above fires, but do it anyway. | |
if (m_buffer) { | |
@@ -1860,6 +1893,11 @@ void HTMLTokenizer::end() | |
if (!m_state.hasTagState()) | |
processToken(); | |
+#if PLATFORM(WKC) | |
+ if (gValidInstances->find(this)==notFound) | |
+ return; | |
+#endif | |
+ | |
fastFree(m_scriptCode); | |
m_scriptCode = 0; | |
m_scriptCodeSize = m_scriptCodeCapacity = m_scriptCodeResync = 0; | |
@@ -1947,6 +1985,7 @@ PassRefPtr<Node> HTMLTokenizer::processToken() | |
// pass the token over to the parser, the parser DOES NOT delete the token | |
n = m_parser->parseToken(&m_currentToken); | |
} | |
+ | |
m_currentToken.reset(); | |
if (scriptController) | |
scriptController->setEventHandlerLineNumber(0); | |
@@ -1965,6 +2004,9 @@ void HTMLTokenizer::processDoctypeToken() | |
HTMLTokenizer::~HTMLTokenizer() | |
{ | |
#if PLATFORM(WKC) | |
+ size_t pos = gValidInstances->find(this); | |
+ if (pos!=notFound) | |
+ gValidInstances->remove(pos); | |
if (m_inWrite && !wkcMemoryIsCrashingPeer()) { | |
// An unexpected error occurred. | |
// This is workaround for issue http://code.google.com/p/chromium/issues/detail?id=50250 | |
@@ -2029,6 +2071,7 @@ void HTMLTokenizer::executeScriptsWaitingForStylesheets() | |
void HTMLTokenizer::notifyFinished(CachedResource*) | |
{ | |
+ RefPtr<HTMLTokenizer> protect(this); | |
executeExternalScriptsIfReady(); | |
} | |
@@ -2047,6 +2090,8 @@ void HTMLTokenizer::executeExternalScriptsIfReady() | |
if (m_hasScriptsWaitingForStylesheets) | |
return; | |
+ RefPtr<HTMLTokenizer> protect(this); | |
+ | |
bool finished = false; | |
double startTime = currentTime(); | |
@@ -2150,11 +2195,12 @@ void HTMLTokenizer::setSrc(const SegmentedString& source) | |
void parseHTMLDocumentFragment(const String& source, DocumentFragment* fragment) | |
{ | |
- HTMLTokenizer tok(fragment); | |
- tok.setForceSynchronous(true); | |
- tok.write(source, true); | |
- tok.finish(); | |
- ASSERT(!tok.processingData()); // make sure we're done (see 3963151) | |
+ RefPtr<HTMLTokenizer> tok = HTMLTokenizer::create(fragment); | |
+ tok->setForceSynchronous(true); | |
+ tok->write(source, true); | |
+ tok->finish(); | |
+ ASSERT(!tok->processingData()); // make sure we're done (see 3963151) | |
+ tok->detach(); | |
} | |
UChar decodeNamedEntity(const char* name) | |
@@ -2163,4 +2209,12 @@ UChar decodeNamedEntity(const char* name) | |
return e ? e->code : 0; | |
} | |
+#if PLATFORM(WKC) | |
+void | |
+HTMLTokenizer::resetVariables() | |
+{ | |
+ gValidInstances = 0; | |
+} | |
+#endif | |
+ | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLTokenizer.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLTokenizer.h | |
index 2516eda..c6d734d 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLTokenizer.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLTokenizer.h | |
@@ -133,9 +133,18 @@ public: | |
class HTMLTokenizer : public Tokenizer, public CachedResourceClient { | |
public: | |
- HTMLTokenizer(HTMLDocument*, bool reportErrors); | |
- HTMLTokenizer(HTMLViewSourceDocument*); | |
- HTMLTokenizer(DocumentFragment*); | |
+ static PassRefPtr<HTMLTokenizer> create(HTMLDocument* document, bool reportErrors) | |
+ { | |
+ return adoptRef(new HTMLTokenizer(document, reportErrors)); | |
+ } | |
+ static PassRefPtr<HTMLTokenizer> create(HTMLViewSourceDocument* document) | |
+ { | |
+ return adoptRef(new HTMLTokenizer(document)); | |
+ } | |
+ static PassRefPtr<HTMLTokenizer> create(DocumentFragment* fragment) | |
+ { | |
+ return adoptRef(new HTMLTokenizer(fragment)); | |
+ } | |
virtual ~HTMLTokenizer(); | |
virtual void write(const SegmentedString&, bool appendData); | |
@@ -156,7 +165,16 @@ public: | |
virtual bool isHTMLTokenizer() const { return true; } | |
HTMLParser* htmlParser() const { return m_parser.get(); } | |
+#if PLATFORM(WKC) | |
+ static void resetVariables(); | |
+#endif | |
+ virtual void detach(); | |
+ | |
private: | |
+ HTMLTokenizer(HTMLDocument*, bool reportErrors); | |
+ HTMLTokenizer(HTMLViewSourceDocument*); | |
+ HTMLTokenizer(DocumentFragment*); | |
+ | |
class State; | |
// Where we are in parsing a tag | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLViewSourceDocument.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLViewSourceDocument.cpp | |
index ba718d1..36e8a35 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLViewSourceDocument.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLViewSourceDocument.cpp | |
@@ -51,7 +51,7 @@ HTMLViewSourceDocument::HTMLViewSourceDocument(Frame* frame, const String& mimeT | |
setUsesBeforeAfterRules(true); | |
} | |
-Tokenizer* HTMLViewSourceDocument::createTokenizer() | |
+PassRefPtr<Tokenizer> HTMLViewSourceDocument::createTokenizer() | |
{ | |
// Use HTMLTokenizer if applicable, otherwise use TextTokenizer. | |
if (m_type == "text/html" || m_type == "application/xhtml+xml" || m_type == "image/svg+xml" || implementation()->isXMLMIMEType(m_type) | |
@@ -59,7 +59,7 @@ Tokenizer* HTMLViewSourceDocument::createTokenizer() | |
|| m_type == "application/vnd.wap.xhtml+xml" | |
#endif | |
) { | |
- return new HTMLTokenizer(this); | |
+ return HTMLTokenizer::create(this); | |
} | |
return createTextTokenizer(this); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLViewSourceDocument.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLViewSourceDocument.h | |
index e4eadb0..87bc730 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/HTMLViewSourceDocument.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/HTMLViewSourceDocument.h | |
@@ -50,7 +50,7 @@ private: | |
HTMLViewSourceDocument(Frame*, const String& mimeType); | |
// Returns HTMLTokenizer or TextTokenizer based on m_type. | |
- virtual Tokenizer* createTokenizer(); | |
+ virtual PassRefPtr<Tokenizer> createTokenizer(); | |
void createContainingTable(); | |
PassRefPtr<Element> addSpanWithClassName(const String&); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/canvas/CanvasRenderingContext2D.cpp | |
index 4ba9c1b..cc8da50 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/html/canvas/CanvasRenderingContext2D.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/html/canvas/CanvasRenderingContext2D.cpp | |
@@ -1236,7 +1236,7 @@ PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageEleme | |
PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElement* canvas, | |
const String& repetitionType, ExceptionCode& ec) | |
{ | |
- if (!canvas->width() || !canvas->height()) { | |
+ if (!canvas->width() || !canvas->height() || !canvas->buffer()) { | |
ec = INVALID_STATE_ERR; | |
return 0; | |
} | |
@@ -1305,6 +1305,13 @@ PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float | |
scaledSize.setWidth(1); | |
if (scaledSize.height() < 1) | |
scaledSize.setHeight(1); | |
+ | |
+#if PLATFORM(WKC) | |
+ if (scaledSize.width() > 32767 || scaledSize.height() > 32767) { | |
+ ec = NOT_SUPPORTED_ERR; | |
+ return 0; | |
+ } | |
+#endif | |
return createEmptyImageData(scaledSize); | |
} | |
@@ -1403,6 +1410,7 @@ void CanvasRenderingContext2D::setFont(const String& newFont) | |
RefPtr<RenderStyle> newStyle = RenderStyle::create(); | |
if (canvas()->computedStyle()) | |
newStyle->setFontDescription(canvas()->computedStyle()->fontDescription()); | |
+ newStyle->font().update(newStyle->font().fontSelector()); | |
// Now map the font property into the style. | |
CSSStyleSelector* styleSelector = canvas()->document()->styleSelector(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/DocumentThreadableLoader.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/DocumentThreadableLoader.cpp | |
index de0a0b0..8a4b665 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/DocumentThreadableLoader.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/DocumentThreadableLoader.cpp | |
@@ -81,16 +81,18 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document* document, Threadabl | |
ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); | |
- if (!m_options.forcePreflight && isSimpleCrossOriginAccessRequest(request.httpMethod(), request.httpHeaderFields())) | |
- makeSimpleCrossOriginAccessRequest(request); | |
- else { | |
- m_actualRequest.set(new ResourceRequest(request)); | |
- m_actualRequest->setAllowCookies(m_options.allowCredentials); | |
+ OwnPtr<ResourceRequest> crossOriginRequest(new ResourceRequest(request)); | |
+ crossOriginRequest->removeCredentials(); | |
+ crossOriginRequest->setAllowCookies(m_options.allowCredentials); | |
- if (CrossOriginPreflightResultCache::shared().canSkipPreflight(document->securityOrigin()->toString(), request.url(), m_options.allowCredentials, request.httpMethod(), request.httpHeaderFields())) | |
+ if (!m_options.forcePreflight && isSimpleCrossOriginAccessRequest(crossOriginRequest->httpMethod(), crossOriginRequest->httpHeaderFields())) | |
+ makeSimpleCrossOriginAccessRequest(*crossOriginRequest); | |
+ else { | |
+ m_actualRequest.set(crossOriginRequest.release()); | |
+ if (CrossOriginPreflightResultCache::shared().canSkipPreflight(document->securityOrigin()->toString(), m_actualRequest->url(), m_options.allowCredentials, m_actualRequest->httpMethod(), m_actualRequest->httpHeaderFields())) | |
preflightSuccess(); | |
else | |
- makeCrossOriginAccessRequestWithPreflight(request); | |
+ makeCrossOriginAccessRequestWithPreflight(*m_actualRequest); | |
} | |
} | |
@@ -106,8 +108,6 @@ void DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest(const Resource | |
// Make a copy of the passed request so that we can modify some details. | |
ResourceRequest crossOriginRequest(request); | |
- crossOriginRequest.removeCredentials(); | |
- crossOriginRequest.setAllowCookies(m_options.allowCredentials); | |
crossOriginRequest.setHTTPOrigin(m_document->securityOrigin()->toString()); | |
loadRequest(crossOriginRequest, DoSecurityCheck); | |
@@ -155,6 +155,9 @@ void DocumentThreadableLoader::cancel() | |
return; | |
m_loader->cancel(); | |
+#if PLATFORM(WKC) | |
+ if (m_loader) | |
+#endif | |
m_loader->clearClient(); | |
m_loader = 0; | |
m_client = 0; | |
@@ -287,11 +290,17 @@ void DocumentThreadableLoader::preflightSuccess() | |
void DocumentThreadableLoader::preflightFailure() | |
{ | |
+ m_actualRequest = 0; // Prevent didFinishLoading() from bypassing access check. | |
m_client->didFail(ResourceError()); | |
} | |
void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, SecurityCheckPolicy securityCheck) | |
{ | |
+ // Any credential should have been removed from the cross-site requests. | |
+ const KURL& requestURL = request.url(); | |
+ ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); | |
+ ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); | |
+ | |
if (m_async) { | |
// Don't sniff content or send load callbacks for the preflight request. | |
bool sendLoadCallbacks = m_options.sendLoadCallbacks && !m_actualRequest; | |
@@ -315,15 +324,15 @@ void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Secur | |
// No exception for file:/// resources, see <rdar://problem/4962298>. | |
// Also, if we have an HTTP response, then it wasn't a network error in fact. | |
- if (!error.isNull() && !request.url().isLocalFile() && response.httpStatusCode() <= 0) { | |
+ if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode() <= 0) { | |
m_client->didFail(error); | |
return; | |
} | |
// FIXME: FrameLoader::loadSynchronously() does not tell us whether a redirect happened or not, so we guess by comparing the | |
// request and response URLs. This isn't a perfect test though, since a server can serve a redirect to the same URL that was | |
- // requested. | |
- if (request.url() != response.url() && !isAllowedRedirect(response.url())) { | |
+ // requested. Also comparing the request and response URLs as strings will fail if the requestURL still has its credentials. | |
+ if (requestURL != response.url() && !isAllowedRedirect(response.url())) { | |
m_client->didFailRedirectCheck(); | |
return; | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/FTPDirectoryDocument.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/FTPDirectoryDocument.cpp | |
index ee0f4ca..01da51d 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/FTPDirectoryDocument.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/FTPDirectoryDocument.cpp | |
@@ -55,7 +55,10 @@ using namespace HTMLNames; | |
class FTPDirectoryTokenizer : public HTMLTokenizer { | |
public: | |
- FTPDirectoryTokenizer(HTMLDocument*); | |
+ passRefPtr<FTPDirectoryTokenizer> create(HTMLDocument* document) | |
+ { | |
+ return adoptRef(new FTPDirectoryTokenizer(document)); | |
+ } | |
virtual void write(const SegmentedString&, bool appendData); | |
virtual void finish(); | |
@@ -75,6 +78,8 @@ public: | |
} | |
private: | |
+ FTPDirectoryTokenizer(HTMLDocument*); | |
+ | |
// The tokenizer will attempt to load the document template specified via the preference | |
// Failing that, it will fall back and create the basic document which will have a minimal | |
// table for presenting the FTP directory in a useful manner | |
@@ -489,9 +494,9 @@ FTPDirectoryDocument::FTPDirectoryDocument(Frame* frame) | |
#endif | |
} | |
-Tokenizer* FTPDirectoryDocument::createTokenizer() | |
+PassRefPtr<Tokenizer> FTPDirectoryDocument::createTokenizer() | |
{ | |
- return new FTPDirectoryTokenizer(this); | |
+ return adoptRef(new FTPDirectoryTokenizer(this)); | |
} | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/FTPDirectoryDocument.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/FTPDirectoryDocument.h | |
index b208c4e..5e30816 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/FTPDirectoryDocument.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/FTPDirectoryDocument.h | |
@@ -40,7 +40,7 @@ public: | |
private: | |
FTPDirectoryDocument(Frame*); | |
- virtual Tokenizer* createTokenizer(); | |
+ virtual PassRefPtr<Tokenizer> createTokenizer(); | |
}; | |
} // namespace WebCore | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/FrameLoader.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/FrameLoader.cpp | |
index 16ebe9c..575f14e 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/FrameLoader.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/FrameLoader.cpp | |
@@ -218,7 +218,8 @@ FrameLoader::~FrameLoader() | |
void FrameLoader::init() | |
{ | |
- // this somewhat odd set of steps is needed to give the frame an initial empty document | |
+ // This somewhat odd set of steps gives the frame an initial empty document. | |
+ // It would be better if this could be done with even fewer steps. | |
m_isDisplayingInitialEmptyDocument = false; | |
m_creatingInitialEmptyDocument = true; | |
setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(KURL(ParsedURLString, "")), SubstituteData()).get()); | |
@@ -488,9 +489,7 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F | |
if (!m_outgoingReferrer.isEmpty()) | |
frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer); | |
- if (strcmp(action, "GET") == 0) | |
- u.setQuery(formData->flattenToString()); | |
- else { | |
+ if (strcmp(action, "POST") == 0) { | |
frameRequest.resourceRequest().setHTTPMethod("POST"); | |
frameRequest.resourceRequest().setHTTPBody(formData); | |
@@ -499,9 +498,13 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F | |
frameRequest.resourceRequest().setHTTPContentType(contentType); | |
else // contentType must be "multipart/form-data" | |
frameRequest.resourceRequest().setHTTPContentType(contentType + "; boundary=" + boundary); | |
+ frameRequest.resourceRequest().setURL(u); | |
+ } else { | |
+ KURL requestURL(u); | |
+ requestURL.setQuery(formData->flattenToString()); | |
+ frameRequest.resourceRequest().setURL(requestURL); | |
} | |
- frameRequest.resourceRequest().setURL(u); | |
addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin()); | |
targetFrame->redirectScheduler()->scheduleFormSubmission(frameRequest, lockHistory, event, formState); | |
@@ -621,7 +624,8 @@ KURL FrameLoader::iconURL() | |
return KURL(); | |
KURL url; | |
- url.setProtocol(m_URL.protocol()); | |
+ bool couldSetProtocol = url.setProtocol(m_URL.protocol()); | |
+ ASSERT_UNUSED(couldSetProtocol, couldSetProtocol); | |
url.setHost(m_URL.host()); | |
if (m_URL.hasPort()) | |
url.setPort(m_URL.port()); | |
@@ -2843,10 +2847,8 @@ void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame() | |
void FrameLoader::finishedLoadingDocument(DocumentLoader* loader) | |
{ | |
// FIXME: Platforms shouldn't differ here! | |
-#if PLATFORM(WIN) || PLATFORM(CHROMIUM) | |
if (m_creatingInitialEmptyDocument) | |
return; | |
-#endif | |
// If loading a webarchive, run through webarchive machinery | |
const String& responseMIMEType = loader->responseMIMEType(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/ImageDocument.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/ImageDocument.cpp | |
index 9b5598d..f9e29b4 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/ImageDocument.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/ImageDocument.cpp | |
@@ -77,7 +77,10 @@ private: | |
class ImageTokenizer : public Tokenizer { | |
public: | |
- ImageTokenizer(ImageDocument* doc) : m_doc(doc) {} | |
+ static PassRefPtr<ImageTokenizer> create(ImageDocument* doc) | |
+ { | |
+ return adoptRef(new ImageTokenizer(doc)); | |
+ } | |
virtual void write(const SegmentedString&, bool appendData); | |
virtual void finish(); | |
@@ -87,6 +90,8 @@ public: | |
virtual bool writeRawData(const char* data, int len); | |
private: | |
+ ImageTokenizer(ImageDocument* doc) : m_doc(doc) {} | |
+private: | |
ImageDocument* m_doc; | |
}; | |
@@ -173,9 +178,9 @@ ImageDocument::ImageDocument(Frame* frame) | |
setParseMode(Compat); | |
} | |
-Tokenizer* ImageDocument::createTokenizer() | |
+PassRefPtr<Tokenizer> ImageDocument::createTokenizer() | |
{ | |
- return new ImageTokenizer(this); | |
+ return ImageTokenizer::create(this); | |
} | |
void ImageDocument::createDocumentStructure() | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/ImageDocument.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/ImageDocument.h | |
index 080b250..2aec3b8 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/ImageDocument.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/ImageDocument.h | |
@@ -49,7 +49,7 @@ public: | |
private: | |
ImageDocument(Frame*); | |
- virtual Tokenizer* createTokenizer(); | |
+ virtual PassRefPtr<Tokenizer> createTokenizer(); | |
virtual bool isImageDocument() const { return true; } | |
void createDocumentStructure(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/MediaDocument.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/MediaDocument.cpp | |
index 656d0a0..c162770 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/MediaDocument.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/MediaDocument.cpp | |
@@ -53,9 +53,14 @@ using namespace HTMLNames; | |
class MediaTokenizer : public Tokenizer { | |
public: | |
- MediaTokenizer(Document* doc) : m_doc(doc), m_mediaElement(0) {} | |
+ static PassRefPtr<MediaTokenizer> create(Document* doc) | |
+ { | |
+ return adoptRef(new MediaTokenizer(doc)); | |
+ } | |
private: | |
+ MediaTokenizer(Document* doc) : m_doc(doc), m_mediaElement(0) {} | |
+ | |
virtual void write(const SegmentedString&, bool appendData); | |
virtual void stopParsing(); | |
virtual void finish(); | |
@@ -145,9 +150,9 @@ MediaDocument::~MediaDocument() | |
ASSERT(!m_replaceMediaElementTimer.isActive()); | |
} | |
-Tokenizer* MediaDocument::createTokenizer() | |
+PassRefPtr<Tokenizer> MediaDocument::createTokenizer() | |
{ | |
- return new MediaTokenizer(this); | |
+ return MediaTokenizer::create(this); | |
} | |
void MediaDocument::defaultEventHandler(Event* event) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/MediaDocument.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/MediaDocument.h | |
index aa751ab..398fb3f 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/MediaDocument.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/MediaDocument.h | |
@@ -46,7 +46,7 @@ private: | |
MediaDocument(Frame*); | |
virtual bool isMediaDocument() const { return true; } | |
- virtual Tokenizer* createTokenizer(); | |
+ virtual PassRefPtr<Tokenizer> createTokenizer(); | |
virtual void defaultEventHandler(Event*); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/PluginDocument.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/PluginDocument.cpp | |
index 788691f..dcdb7e7 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/PluginDocument.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/PluginDocument.cpp | |
@@ -46,9 +46,14 @@ using namespace HTMLNames; | |
class PluginTokenizer : public Tokenizer { | |
public: | |
- PluginTokenizer(Document* doc) : m_doc(doc), m_embedElement(0) {} | |
+ static PassRefPtr<PluginTokenizer> create(Document* doc) | |
+ { | |
+ return adoptRef(new PluginTokenizer(doc)); | |
+ } | |
private: | |
+ PluginTokenizer(Document* doc) : m_doc(doc), m_embedElement(0) {} | |
+ | |
virtual void write(const SegmentedString&, bool appendData); | |
virtual void stopParsing(); | |
virtual void finish(); | |
@@ -142,9 +147,9 @@ PluginDocument::PluginDocument(Frame* frame) | |
setParseMode(Compat); | |
} | |
-Tokenizer* PluginDocument::createTokenizer() | |
+PassRefPtr<Tokenizer> PluginDocument::createTokenizer() | |
{ | |
- return new PluginTokenizer(this); | |
+ return PluginTokenizer::create(this); | |
} | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/PluginDocument.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/PluginDocument.h | |
index 1d5c964..62231bd 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/PluginDocument.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/PluginDocument.h | |
@@ -40,7 +40,7 @@ private: | |
PluginDocument(Frame*); | |
virtual bool isPluginDocument() const { return true; } | |
- virtual Tokenizer* createTokenizer(); | |
+ virtual PassRefPtr<Tokenizer> createTokenizer(); | |
}; | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/RedirectScheduler.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/RedirectScheduler.cpp | |
index e53a1db..d0a03dc 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/RedirectScheduler.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/RedirectScheduler.cpp | |
@@ -160,17 +160,21 @@ void RedirectScheduler::scheduleRedirect(double delay, const String& url) | |
if (url.isEmpty()) | |
return; | |
- // We want a new history item if the refresh timeout is > 1 second. | |
+ // We want a new back/forward list item if the refresh timeout is > 1 second. | |
if (!m_scheduledRedirection || delay <= m_scheduledRedirection->delay) | |
schedule(new ScheduledRedirection(delay, url, true, delay <= 1, false, false)); | |
} | |
-bool RedirectScheduler::mustLockBackForwardList(Frame* targetFrame) | |
+bool RedirectScheduler::mustLockBackForwardList(Frame* targetFrame, bool wasUserGesture) | |
{ | |
+ // Non-user navigation before the page has loaded should not create a new back/forward item. | |
+ // See https://webkit.org/b/42861 for the original motivation for this. | |
+ if (!wasUserGesture && targetFrame->loader()->documentLoader() && targetFrame->loader()->documentLoader()->isLoadingInAPISense()) | |
+ return true; | |
+ | |
// Navigation of a subframe during loading of an ancestor frame does not create a new back/forward item. | |
// The definition of "during load" is any time before all handlers for the load event have been run. | |
// See https://bugs.webkit.org/show_bug.cgi?id=14957 for the original motivation for this. | |
- | |
for (Frame* ancestor = targetFrame->tree()->parent(); ancestor; ancestor = ancestor->tree()->parent()) { | |
Document* document = ancestor->document(); | |
if (!ancestor->loader()->isComplete() || (document && document->processingLoadEvent())) | |
@@ -187,7 +191,7 @@ void RedirectScheduler::scheduleLocationChange(const String& url, const String& | |
if (url.isEmpty()) | |
return; | |
- lockBackForwardList = lockBackForwardList || mustLockBackForwardList(m_frame); | |
+ lockBackForwardList = lockBackForwardList || mustLockBackForwardList(m_frame, wasUserGesture); | |
FrameLoader* loader = m_frame->loader(); | |
@@ -223,7 +227,7 @@ void RedirectScheduler::scheduleFormSubmission(const FrameLoadRequest& frameRequ | |
// to match IE and Opera. | |
// See https://bugs.webkit.org/show_bug.cgi?id=32383 for the original motivation for this. | |
- bool lockBackForwardList = mustLockBackForwardList(m_frame) || (formState->formSubmissionTrigger() == SubmittedByJavaScript && m_frame->tree()->parent()); | |
+ bool lockBackForwardList = mustLockBackForwardList(m_frame, m_frame->script()->processingUserGesture()) || (formState->formSubmissionTrigger() == SubmittedByJavaScript && m_frame->tree()->parent()); | |
schedule(new ScheduledRedirection(frameRequest, lockHistory, lockBackForwardList, event, formState, duringLoad)); | |
} | |
@@ -365,9 +369,13 @@ void RedirectScheduler::startTimer() | |
m_scheduledRedirection->lockBackForwardList); | |
return; | |
case ScheduledRedirection::formSubmission: | |
- // FIXME: It would make sense to report form submissions as client redirects too. | |
- // But we didn't do that in the past when form submission used a separate delay | |
- // mechanism, so doing it will be a behavior change. | |
+ if (m_scheduledRedirection->toldClient) | |
+ return; | |
+ m_scheduledRedirection->toldClient = true; | |
+ loader->clientRedirected(m_scheduledRedirection->frameRequest.resourceRequest().url(), | |
+ m_scheduledRedirection->delay, | |
+ currentTime() + m_timer.nextFireInterval(), | |
+ m_scheduledRedirection->lockBackForwardList); | |
return; | |
case ScheduledRedirection::historyNavigation: | |
// Don't report history navigations. | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/RedirectScheduler.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/RedirectScheduler.h | |
index 005a173..6e9a5f8 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/RedirectScheduler.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/RedirectScheduler.h | |
@@ -69,7 +69,7 @@ private: | |
void timerFired(Timer<RedirectScheduler>*); | |
void schedule(PassOwnPtr<ScheduledRedirection>); | |
- static bool mustLockBackForwardList(Frame* targetFrame); | |
+ static bool mustLockBackForwardList(Frame* targetFrame, bool mustLockIfDuringLoad); | |
Frame* m_frame; | |
Timer<RedirectScheduler> m_timer; | |
@@ -78,4 +78,4 @@ private: | |
} // namespace WebCore | |
-#endif // FrameLoader_h | |
+#endif // RedirectScheduler_h | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/TextDocument.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/TextDocument.cpp | |
index a3d7061..258dfeb 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/TextDocument.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/TextDocument.cpp | |
@@ -40,9 +40,15 @@ using namespace HTMLNames; | |
class TextTokenizer : public Tokenizer { | |
public: | |
- TextTokenizer(Document*); | |
+ static PassRefPtr<TextTokenizer> create(Document* document) | |
+ { | |
+ return adoptRef(new TextTokenizer(document)); | |
+ } | |
+ static PassRefPtr<TextTokenizer> create(HTMLViewSourceDocument* document) | |
+ { | |
+ return adoptRef(new TextTokenizer(document)); | |
+ } | |
virtual ~TextTokenizer(); | |
- TextTokenizer(HTMLViewSourceDocument*); | |
virtual void write(const SegmentedString&, bool appendData); | |
virtual void finish(); | |
@@ -59,7 +65,11 @@ public: | |
m_size = newSize; | |
} | |
} | |
- | |
+ | |
+private: | |
+ TextTokenizer(Document*); | |
+ TextTokenizer(HTMLViewSourceDocument*); | |
+ | |
private: | |
Document* m_doc; | |
Element* m_preElement; | |
@@ -183,14 +193,14 @@ TextDocument::TextDocument(Frame* frame) | |
{ | |
} | |
-Tokenizer* TextDocument::createTokenizer() | |
+PassRefPtr<Tokenizer> TextDocument::createTokenizer() | |
{ | |
- return new TextTokenizer(this); | |
+ return TextTokenizer::create(this); | |
} | |
-Tokenizer* createTextTokenizer(HTMLViewSourceDocument* document) | |
+PassRefPtr<Tokenizer> createTextTokenizer(HTMLViewSourceDocument* document) | |
{ | |
- return new TextTokenizer(document); | |
+ return TextTokenizer::create(document); | |
} | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/TextDocument.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/TextDocument.h | |
index 53e3074..42cfd82 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/loader/TextDocument.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/loader/TextDocument.h | |
@@ -41,10 +41,10 @@ public: | |
private: | |
TextDocument(Frame*); | |
- virtual Tokenizer* createTokenizer(); | |
+ virtual PassRefPtr<Tokenizer> createTokenizer(); | |
}; | |
-Tokenizer* createTextTokenizer(HTMLViewSourceDocument*); | |
+PassRefPtr<Tokenizer> createTextTokenizer(HTMLViewSourceDocument*); | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/DOMSelection.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/DOMSelection.cpp | |
index 0d21c56..d4576a1 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/DOMSelection.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/DOMSelection.cpp | |
@@ -207,6 +207,10 @@ void DOMSelection::collapse(Node* node, int offset, ExceptionCode& ec) | |
ec = INDEX_SIZE_ERR; | |
return; | |
} | |
+ | |
+ if (!isValidForPosition(node)) | |
+ return; | |
+ | |
m_frame->selection()->moveTo(VisiblePosition(node, offset, DOWNSTREAM)); | |
} | |
@@ -244,6 +248,10 @@ void DOMSelection::setBaseAndExtent(Node* baseNode, int baseOffset, Node* extent | |
ec = INDEX_SIZE_ERR; | |
return; | |
} | |
+ | |
+ if (!isValidForPosition(baseNode) || !isValidForPosition(extentNode)) | |
+ return; | |
+ | |
VisiblePosition visibleBase = VisiblePosition(baseNode, baseOffset, DOWNSTREAM); | |
VisiblePosition visibleExtent = VisiblePosition(extentNode, extentOffset, DOWNSTREAM); | |
@@ -258,6 +266,10 @@ void DOMSelection::setPosition(Node* node, int offset, ExceptionCode& ec) | |
ec = INDEX_SIZE_ERR; | |
return; | |
} | |
+ | |
+ if (!isValidForPosition(node)) | |
+ return; | |
+ | |
m_frame->selection()->moveTo(VisiblePosition(node, offset, DOWNSTREAM)); | |
} | |
@@ -320,14 +332,16 @@ void DOMSelection::extend(Node* node, int offset, ExceptionCode& ec) | |
ec = TYPE_MISMATCH_ERR; | |
return; | |
} | |
+ | |
if (offset < 0 || offset > (node->offsetInCharacters() ? caretMaxOffset(node) : (int)node->childNodeCount())) { | |
ec = INDEX_SIZE_ERR; | |
return; | |
} | |
- SelectionController* selection = m_frame->selection(); | |
- selection->expandUsingGranularity(CharacterGranularity); | |
- selection->setExtent(VisiblePosition(node, offset, DOWNSTREAM)); | |
+ if (!isValidForPosition(node)) | |
+ return; | |
+ | |
+ m_frame->selection()->setExtent(VisiblePosition(node, offset, DOWNSTREAM)); | |
} | |
PassRefPtr<Range> DOMSelection::getRangeAt(int index, ExceptionCode& ec) | |
@@ -413,6 +427,8 @@ void DOMSelection::deleteFromDocument() | |
selection->modify(SelectionController::EXTEND, SelectionController::BACKWARD, CharacterGranularity); | |
RefPtr<Range> selectedRange = selection->selection().toNormalizedRange(); | |
+ if (!selectedRange) | |
+ return; | |
ExceptionCode ec = 0; | |
selectedRange->deleteContents(ec); | |
@@ -429,7 +445,7 @@ bool DOMSelection::containsNode(const Node* n, bool allowPartial) const | |
SelectionController* selection = m_frame->selection(); | |
- if (!n || selection->isNone()) | |
+ if (!n || m_frame->document() != n->document() || selection->isNone()) | |
return false; | |
Node* parentNode = n->parentNode(); | |
@@ -472,4 +488,12 @@ String DOMSelection::toString() | |
return plainText(m_frame->selection()->selection().toNormalizedRange().get()); | |
} | |
+bool DOMSelection::isValidForPosition(Node* node) const | |
+{ | |
+ ASSERT(m_frame); | |
+ if (!node) | |
+ return true; | |
+ return node->document() == m_frame->document(); | |
+} | |
+ | |
} // namespace WebCore | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/DOMSelection.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/DOMSelection.h | |
index e0fe1e3..0287e44 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/DOMSelection.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/DOMSelection.h | |
@@ -96,6 +96,7 @@ namespace WebCore { | |
// Convenience method for accessors, does not NULL check m_frame. | |
const VisibleSelection& visibleSelection() const; | |
+ bool isValidForPosition(Node*) const; | |
Frame* m_frame; | |
}; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/DOMTimer.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/DOMTimer.cpp | |
index d6e15f7..12b53d7 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/DOMTimer.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/DOMTimer.cpp | |
@@ -48,7 +48,7 @@ static int timerNestingLevel = 0; | |
static int lastUsedTimeoutId = 0; | |
#endif | |
-DOMTimer::DOMTimer(ScriptExecutionContext* context, ScheduledAction* action, int timeout, bool singleShot) | |
+DOMTimer::DOMTimer(ScriptExecutionContext* context, PassOwnPtr<ScheduledAction> action, int timeout, bool singleShot) | |
: ActiveDOMObject(context, this) | |
, m_action(action) | |
, m_nextFireInterval(0) | |
@@ -89,7 +89,7 @@ DOMTimer::~DOMTimer() | |
scriptExecutionContext()->removeTimeout(m_timeoutId); | |
} | |
-int DOMTimer::install(ScriptExecutionContext* context, ScheduledAction* action, int timeout, bool singleShot) | |
+int DOMTimer::install(ScriptExecutionContext* context, PassOwnPtr<ScheduledAction> action, int timeout, bool singleShot) | |
{ | |
// DOMTimer constructor links the new timer into a list of ActiveDOMObjects held by the 'context'. | |
// The timer is deleted when context is deleted (DOMTimer::contextDestroyed) or explicitly via DOMTimer::removeById(), | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/DOMTimer.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/DOMTimer.h | |
index 14a343e..aa0d677 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/DOMTimer.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/DOMTimer.h | |
@@ -29,20 +29,21 @@ | |
#define DOMTimer_h | |
#include "ActiveDOMObject.h" | |
+#include "ScheduledAction.h" | |
#include "Timer.h" | |
#include <wtf/OwnPtr.h> | |
+#include <wtf/PassOwnPtr.h> | |
namespace WebCore { | |
class InspectorTimelineAgent; | |
- class ScheduledAction; | |
class DOMTimer : public TimerBase, public ActiveDOMObject { | |
public: | |
virtual ~DOMTimer(); | |
// Creates a new timer owned by specified ScriptExecutionContext, starts it | |
// and returns its Id. | |
- static int install(ScriptExecutionContext*, ScheduledAction*, int timeout, bool singleShot); | |
+ static int install(ScriptExecutionContext*, PassOwnPtr<ScheduledAction>, int timeout, bool singleShot); | |
static void removeById(ScriptExecutionContext*, int timeoutId); | |
// ActiveDOMObject | |
@@ -64,7 +65,7 @@ namespace WebCore { | |
#endif | |
private: | |
- DOMTimer(ScriptExecutionContext*, ScheduledAction*, int timeout, bool singleShot); | |
+ DOMTimer(ScriptExecutionContext*, PassOwnPtr<ScheduledAction>, int timeout, bool singleShot); | |
virtual void fired(); | |
int m_timeoutId; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/DOMWindow.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/DOMWindow.cpp | |
index ad922b5..6136c59 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/DOMWindow.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/DOMWindow.cpp | |
@@ -1185,7 +1185,7 @@ void DOMWindow::scrollTo(int x, int y) const | |
m_frame->document()->updateLayoutIgnorePendingStylesheets(); | |
- FrameView* view = m_frame->view(); | |
+ RefPtr<FrameView> view = m_frame->view(); | |
if (!view) | |
return; | |
@@ -1274,24 +1274,40 @@ void DOMWindow::resizeTo(float width, float height) const | |
page->chrome()->setWindowRect(fr); | |
} | |
-int DOMWindow::setTimeout(ScheduledAction* action, int timeout) | |
+int DOMWindow::setTimeout(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec) | |
{ | |
- return DOMTimer::install(scriptExecutionContext(), action, timeout, true); | |
+ ScriptExecutionContext* context = scriptExecutionContext(); | |
+ if (!context) { | |
+ ec = INVALID_ACCESS_ERR; | |
+ return -1; | |
+ } | |
+ return DOMTimer::install(context, action, timeout, true); | |
} | |
void DOMWindow::clearTimeout(int timeoutId) | |
{ | |
- DOMTimer::removeById(scriptExecutionContext(), timeoutId); | |
+ ScriptExecutionContext* context = scriptExecutionContext(); | |
+ if (!context) | |
+ return; | |
+ DOMTimer::removeById(context, timeoutId); | |
} | |
-int DOMWindow::setInterval(ScheduledAction* action, int timeout) | |
+int DOMWindow::setInterval(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec) | |
{ | |
- return DOMTimer::install(scriptExecutionContext(), action, timeout, false); | |
+ ScriptExecutionContext* context = scriptExecutionContext(); | |
+ if (!context) { | |
+ ec = INVALID_ACCESS_ERR; | |
+ return -1; | |
+ } | |
+ return DOMTimer::install(context, action, timeout, false); | |
} | |
void DOMWindow::clearInterval(int timeoutId) | |
{ | |
- DOMTimer::removeById(scriptExecutionContext(), timeoutId); | |
+ ScriptExecutionContext* context = scriptExecutionContext(); | |
+ if (!context) | |
+ return; | |
+ DOMTimer::removeById(context, timeoutId); | |
} | |
bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/DOMWindow.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/DOMWindow.h | |
index 50dade0..7371581 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/DOMWindow.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/DOMWindow.h | |
@@ -238,9 +238,9 @@ namespace WebCore { | |
void resizeTo(float width, float height) const; | |
// Timers | |
- int setTimeout(ScheduledAction*, int timeout); | |
+ int setTimeout(PassOwnPtr<ScheduledAction>, int timeout, ExceptionCode&); | |
void clearTimeout(int timeoutId); | |
- int setInterval(ScheduledAction*, int timeout); | |
+ int setInterval(PassOwnPtr<ScheduledAction>, int timeout, ExceptionCode&); | |
void clearInterval(int timeoutId); | |
// Events | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/FocusController.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/FocusController.cpp | |
index 4e296c0..11f7c96 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/FocusController.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/FocusController.cpp | |
@@ -1,7 +1,7 @@ | |
/* | |
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved. | |
* Copyright (C) 2008 Nuanti Ltd. | |
- * Copyright (c) 2010, 2011 ACCESS CO., LTD. All rights reserved. | |
+ * Copyright (c) 2010, 2011, 2013 ACCESS CO., LTD. All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
@@ -416,8 +416,15 @@ void FocusController::findFocusableNodeInDirection(Node* outer, Node* focusedNod | |
candidate.enclosingScrollableBox = candidateParent.node; | |
} else if (!isInRootDocument(outer)) { | |
+#if PLATFORM(WKC) | |
+ if (outer->parent() && outer->parent()->isDocumentNode()) { | |
+ Document* document = static_cast<Document*>(outer->parent()); | |
+ candidate.enclosingScrollableBox = static_cast<Node*>(document->ownerElement()); | |
+ } | |
+#else | |
if (Document* document = static_cast<Document*>(outer->parent())) | |
candidate.enclosingScrollableBox = static_cast<Node*>(document->ownerElement()); | |
+#endif | |
} else if (isScrollableContainerNode(outer->parent())) | |
candidate.enclosingScrollableBox = outer->parent(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/Frame.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/Frame.cpp | |
index 0f31f90..5a871c2 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/Frame.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/Frame.cpp | |
@@ -1,1978 +1,1992 @@ | |
-/* | |
- * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> | |
- * 1999 Lars Knoll <knoll@kde.org> | |
- * 1999 Antti Koivisto <koivisto@kde.org> | |
- * 2000 Simon Hausmann <hausmann@kde.org> | |
- * 2000 Stefan Schimanski <1Stein@gmx.de> | |
- * 2001 George Staikos <staikos@kde.org> | |
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | |
- * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com> | |
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | |
- * Copyright (C) 2008 Eric Seidel <eric@webkit.org> | |
- * Copyright (c) 2010 ACCESS CO., LTD. All rights reserved. | |
- * | |
- * This library is free software; you can redistribute it and/or | |
- * modify it under the terms of the GNU Library General Public | |
- * License as published by the Free Software Foundation; either | |
- * version 2 of the License, or (at your option) any later version. | |
- * | |
- * This library is distributed in the hope that it will be useful, | |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
- * Library General Public License for more details. | |
- * | |
- * You should have received a copy of the GNU Library General Public License | |
- * along with this library; see the file COPYING.LIB. If not, write to | |
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
- * Boston, MA 02110-1301, USA. | |
- */ | |
- | |
-#include "config.h" | |
-#include "Frame.h" | |
- | |
-#include "ApplyStyleCommand.h" | |
-#include "BeforeUnloadEvent.h" | |
-#include "CSSComputedStyleDeclaration.h" | |
-#include "CSSMutableStyleDeclaration.h" | |
-#include "CSSProperty.h" | |
-#include "CSSPropertyNames.h" | |
-#include "CachedCSSStyleSheet.h" | |
-#include "Chrome.h" | |
-#include "DOMWindow.h" | |
-#include "DocLoader.h" | |
-#include "DocumentType.h" | |
-#include "EditingText.h" | |
-#include "EditorClient.h" | |
-#include "EventNames.h" | |
-#include "FloatQuad.h" | |
-#include "FocusController.h" | |
-#include "FrameLoader.h" | |
-#include "FrameLoaderClient.h" | |
-#include "FrameView.h" | |
-#include "GraphicsContext.h" | |
-#include "HTMLDocument.h" | |
-#include "HTMLFormControlElement.h" | |
-#include "HTMLFormElement.h" | |
-#include "HTMLFrameElementBase.h" | |
-#include "HTMLNames.h" | |
-#include "HTMLTableCellElement.h" | |
-#include "HitTestResult.h" | |
-#include "Logging.h" | |
-#include "MediaFeatureNames.h" | |
-#include "Navigator.h" | |
-#include "NodeList.h" | |
-#include "Page.h" | |
-#include "PageGroup.h" | |
-#include "RegularExpression.h" | |
-#include "RenderPart.h" | |
-#include "RenderTableCell.h" | |
-#include "RenderTextControl.h" | |
-#include "RenderTheme.h" | |
-#include "RenderView.h" | |
-#include "ScriptController.h" | |
-#include "ScriptSourceCode.h" | |
-#include "ScriptValue.h" | |
-#include "Settings.h" | |
-#include "TextIterator.h" | |
-#include "TextResourceDecoder.h" | |
-#include "UserContentURLPattern.h" | |
-#include "XMLNames.h" | |
-#include "htmlediting.h" | |
-#include "markup.h" | |
-#include "npruntime_impl.h" | |
-#include "visible_units.h" | |
-#include <wtf/RefCountedLeakCounter.h> | |
-#include <wtf/StdLibExtras.h> | |
- | |
-#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) | |
-#import <Carbon/Carbon.h> | |
-#endif | |
- | |
-#if USE(JSC) | |
-#include "JSDOMWindowShell.h" | |
-#include "runtime_root.h" | |
-#endif | |
- | |
-#if ENABLE(SVG) | |
-#include "SVGDocument.h" | |
-#include "SVGDocumentExtensions.h" | |
-#include "SVGNames.h" | |
-#include "XLinkNames.h" | |
-#endif | |
- | |
-#if ENABLE(WML) | |
-#include "WMLNames.h" | |
-#endif | |
- | |
-#if ENABLE(MATHML) | |
-#include "MathMLNames.h" | |
-#endif | |
- | |
-using namespace std; | |
- | |
-namespace WebCore { | |
- | |
-using namespace HTMLNames; | |
- | |
-#ifndef NDEBUG | |
-#if PLATFORM(WKC) | |
-static WTF::RefCountedLeakCounter* gFrameCounter = 0; | |
-#else | |
-static WTF::RefCountedLeakCounter frameCounter("Frame"); | |
-#endif | |
-#endif | |
- | |
-static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement) | |
-{ | |
- if (!ownerElement) | |
- return 0; | |
- return ownerElement->document()->frame(); | |
-} | |
- | |
-Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* frameLoaderClient) | |
- : m_page(page) | |
- , m_treeNode(this, parentFromOwnerElement(ownerElement)) | |
- , m_loader(this, frameLoaderClient) | |
- , m_redirectScheduler(this) | |
- , m_ownerElement(ownerElement) | |
- , m_script(this) | |
- , m_selectionGranularity(CharacterGranularity) | |
- , m_selectionController(this) | |
- , m_caretBlinkTimer(this, &Frame::caretBlinkTimerFired) | |
- , m_editor(this) | |
- , m_eventHandler(this) | |
- , m_animationController(this) | |
- , m_lifeSupportTimer(this, &Frame::lifeSupportTimerFired) | |
-#if ENABLE(ORIENTATION_EVENTS) | |
- , m_orientation(0) | |
-#endif | |
- , m_caretVisible(false) | |
- , m_caretPaint(true) | |
- , m_highlightTextMatches(false) | |
- , m_inViewSourceMode(false) | |
- , m_needsReapplyStyles(false) | |
- , m_isDisconnected(false) | |
- , m_excludeFromTextSearch(false) | |
-{ | |
- Frame* parent = parentFromOwnerElement(ownerElement); | |
- m_zoomFactor = parent ? parent->m_zoomFactor : 1.0f; | |
- | |
- AtomicString::init(); | |
- HTMLNames::init(); | |
- QualifiedName::init(); | |
- MediaFeatureNames::init(); | |
- | |
-#if ENABLE(SVG) | |
- SVGNames::init(); | |
- XLinkNames::init(); | |
-#endif | |
- | |
-#if ENABLE(WML) | |
- WMLNames::init(); | |
-#endif | |
- | |
-#if ENABLE(MATHML) | |
- MathMLNames::init(); | |
-#endif | |
- | |
- XMLNames::init(); | |
- | |
- if (!ownerElement) | |
- page->setMainFrame(this); | |
- else { | |
- page->incrementFrameCount(); | |
- // Make sure we will not end up with two frames referencing the same owner element. | |
- ASSERT((!(ownerElement->m_contentFrame)) || (ownerElement->m_contentFrame->ownerElement() != ownerElement)); | |
- ownerElement->m_contentFrame = this; | |
- } | |
- | |
-#ifndef NDEBUG | |
-#if PLATFORM(WKC) | |
- if (!gFrameCounter) { | |
- gFrameCounter = new WTF::RefCountedLeakCounter("Frame"); | |
- } | |
- WTF::RefCountedLeakCounter& frameCounter = *gFrameCounter; | |
-#endif | |
- frameCounter.increment(); | |
-#endif | |
-} | |
- | |
-Frame::~Frame() | |
-{ | |
- setView(0); | |
- loader()->cancelAndClear(); | |
- | |
- // FIXME: We should not be doing all this work inside the destructor | |
- | |
- ASSERT(!m_lifeSupportTimer.isActive()); | |
- | |
-#ifndef NDEBUG | |
-#if PLATFORM(WKC) | |
- WTF::RefCountedLeakCounter& frameCounter = *gFrameCounter; | |
-#endif | |
- frameCounter.decrement(); | |
-#endif | |
- | |
- disconnectOwnerElement(); | |
- | |
- if (m_domWindow) | |
- m_domWindow->disconnectFrame(); | |
- script()->clearWindowShell(); | |
- | |
- HashSet<DOMWindow*>::iterator end = m_liveFormerWindows.end(); | |
- for (HashSet<DOMWindow*>::iterator it = m_liveFormerWindows.begin(); it != end; ++it) | |
- (*it)->disconnectFrame(); | |
- | |
- if (m_view) { | |
- m_view->hide(); | |
- m_view->clearFrame(); | |
- } | |
- | |
- ASSERT(!m_lifeSupportTimer.isActive()); | |
-} | |
- | |
-void Frame::init() | |
-{ | |
- m_loader.init(); | |
-} | |
- | |
-FrameLoader* Frame::loader() const | |
-{ | |
- return &m_loader; | |
-} | |
- | |
-RedirectScheduler* Frame::redirectScheduler() const | |
-{ | |
- return &m_redirectScheduler; | |
-} | |
- | |
-FrameView* Frame::view() const | |
-{ | |
- return m_view.get(); | |
-} | |
- | |
-void Frame::setView(PassRefPtr<FrameView> view) | |
-{ | |
- // We the custom scroll bars as early as possible to prevent m_doc->detach() | |
- // from messing with the view such that its scroll bars won't be torn down. | |
- // FIXME: We should revisit this. | |
- if (m_view) | |
- m_view->detachCustomScrollbars(); | |
- | |
- // Detach the document now, so any onUnload handlers get run - if | |
- // we wait until the view is destroyed, then things won't be | |
- // hooked up enough for some JavaScript calls to work. | |
- if (!view && m_doc && m_doc->attached() && !m_doc->inPageCache()) { | |
- // FIXME: We don't call willRemove here. Why is that OK? | |
- m_doc->detach(); | |
- if (m_view) | |
- m_view->unscheduleRelayout(); | |
- } | |
- eventHandler()->clear(); | |
- | |
- m_view = view; | |
- | |
- // Only one form submission is allowed per view of a part. | |
- // Since this part may be getting reused as a result of being | |
- // pulled from the back/forward cache, reset this flag. | |
- loader()->resetMultipleFormSubmissionProtection(); | |
-} | |
- | |
-ScriptController* Frame::script() | |
-{ | |
- return &m_script; | |
-} | |
- | |
-Document* Frame::document() const | |
-{ | |
- return m_doc.get(); | |
-} | |
- | |
-void Frame::setDocument(PassRefPtr<Document> newDoc) | |
-{ | |
- if (m_doc && m_doc->attached() && !m_doc->inPageCache()) { | |
- // FIXME: We don't call willRemove here. Why is that OK? | |
- m_doc->detach(); | |
- } | |
- | |
- m_doc = newDoc; | |
- if (m_doc && selection()->isFocusedAndActive()) | |
- setUseSecureKeyboardEntry(m_doc->useSecureKeyboardEntryWhenActive()); | |
- | |
- if (m_doc && !m_doc->attached()) | |
- m_doc->attach(); | |
- | |
- // Update the cached 'document' property, which is now stale. | |
- m_script.updateDocument(); | |
-} | |
- | |
-#if ENABLE(ORIENTATION_EVENTS) | |
-void Frame::sendOrientationChangeEvent(int orientation) | |
-{ | |
- m_orientation = orientation; | |
- if (Document* doc = document()) | |
- doc->dispatchWindowEvent(Event::create(eventNames().orientationchangeEvent, false, false)); | |
-} | |
-#endif // ENABLE(ORIENTATION_EVENTS) | |
- | |
-Settings* Frame::settings() const | |
-{ | |
- return m_page ? m_page->settings() : 0; | |
-} | |
- | |
-String Frame::selectedText() const | |
-{ | |
- return plainText(selection()->toNormalizedRange().get()); | |
-} | |
- | |
-IntRect Frame::firstRectForRange(Range* range) const | |
-{ | |
- int extraWidthToEndOfLine = 0; | |
- ExceptionCode ec = 0; | |
- ASSERT(range->startContainer(ec)); | |
- ASSERT(range->endContainer(ec)); | |
- | |
- InlineBox* startInlineBox; | |
- int startCaretOffset; | |
- range->startPosition().getInlineBoxAndOffset(DOWNSTREAM, startInlineBox, startCaretOffset); | |
- | |
- RenderObject* startRenderer = range->startContainer(ec)->renderer(); | |
- IntRect startCaretRect = startRenderer->localCaretRect(startInlineBox, startCaretOffset, &extraWidthToEndOfLine); | |
- if (startCaretRect != IntRect()) | |
- startCaretRect = startRenderer->localToAbsoluteQuad(FloatRect(startCaretRect)).enclosingBoundingBox(); | |
- | |
- InlineBox* endInlineBox; | |
- int endCaretOffset; | |
- range->endPosition().getInlineBoxAndOffset(UPSTREAM, endInlineBox, endCaretOffset); | |
- | |
- RenderObject* endRenderer = range->endContainer(ec)->renderer(); | |
- IntRect endCaretRect = endRenderer->localCaretRect(endInlineBox, endCaretOffset); | |
- if (endCaretRect != IntRect()) | |
- endCaretRect = endRenderer->localToAbsoluteQuad(FloatRect(endCaretRect)).enclosingBoundingBox(); | |
- | |
- if (startCaretRect.y() == endCaretRect.y()) { | |
- // start and end are on the same line | |
- return IntRect(min(startCaretRect.x(), endCaretRect.x()), | |
- startCaretRect.y(), | |
- abs(endCaretRect.x() - startCaretRect.x()), | |
- max(startCaretRect.height(), endCaretRect.height())); | |
- } | |
- | |
- // start and end aren't on the same line, so go from start to the end of its line | |
- return IntRect(startCaretRect.x(), | |
- startCaretRect.y(), | |
- startCaretRect.width() + extraWidthToEndOfLine, | |
- startCaretRect.height()); | |
-} | |
- | |
-SelectionController* Frame::selection() const | |
-{ | |
- return &m_selectionController; | |
-} | |
- | |
-Editor* Frame::editor() const | |
-{ | |
- return &m_editor; | |
-} | |
- | |
-TextGranularity Frame::selectionGranularity() const | |
-{ | |
- return m_selectionGranularity; | |
-} | |
- | |
-void Frame::setSelectionGranularity(TextGranularity granularity) | |
-{ | |
- m_selectionGranularity = granularity; | |
-} | |
- | |
-SelectionController* Frame::dragCaretController() const | |
-{ | |
- return m_page->dragCaretController(); | |
-} | |
- | |
- | |
-AnimationController* Frame::animation() const | |
-{ | |
- return &m_animationController; | |
-} | |
- | |
-#if PLATFORM(WKC) | |
-static RegularExpression* gWordRegExp = 0; | |
-#endif | |
- | |
-static RegularExpression* createRegExpForLabels(const Vector<String>& labels) | |
-{ | |
- // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being | |
- // the same across calls. We can't do that. | |
- | |
-#if PLATFORM(WKC) | |
- if (!gWordRegExp) { | |
- gWordRegExp = new RegularExpression("\\w", TextCaseSensitive); | |
- } | |
- RegularExpression& wordRegExp = *gWordRegExp; | |
-#else | |
- DEFINE_STATIC_LOCAL(RegularExpression, wordRegExp, ("\\w", TextCaseSensitive)); | |
-#endif | |
- String pattern("("); | |
- unsigned int numLabels = labels.size(); | |
- unsigned int i; | |
- for (i = 0; i < numLabels; i++) { | |
- String label = labels[i]; | |
- | |
- bool startsWithWordChar = false; | |
- bool endsWithWordChar = false; | |
- if (label.length()) { | |
- startsWithWordChar = wordRegExp.match(label.substring(0, 1)) >= 0; | |
- endsWithWordChar = wordRegExp.match(label.substring(label.length() - 1, 1)) >= 0; | |
- } | |
- | |
- if (i) | |
- pattern.append("|"); | |
- // Search for word boundaries only if label starts/ends with "word characters". | |
- // If we always searched for word boundaries, this wouldn't work for languages | |
- // such as Japanese. | |
- if (startsWithWordChar) | |
- pattern.append("\\b"); | |
- pattern.append(label); | |
- if (endsWithWordChar) | |
- pattern.append("\\b"); | |
- } | |
- pattern.append(")"); | |
- return new RegularExpression(pattern, TextCaseInsensitive); | |
-} | |
- | |
-String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell) | |
-{ | |
- RenderObject* cellRenderer = cell->renderer(); | |
- | |
- if (cellRenderer && cellRenderer->isTableCell()) { | |
- RenderTableCell* tableCellRenderer = toRenderTableCell(cellRenderer); | |
- RenderTableCell* cellAboveRenderer = tableCellRenderer->table()->cellAbove(tableCellRenderer); | |
- | |
- if (cellAboveRenderer) { | |
- HTMLTableCellElement* aboveCell = | |
- static_cast<HTMLTableCellElement*>(cellAboveRenderer->node()); | |
- | |
- if (aboveCell) { | |
- // search within the above cell we found for a match | |
- for (Node* n = aboveCell->firstChild(); n; n = n->traverseNextNode(aboveCell)) { | |
- if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) { | |
- // For each text chunk, run the regexp | |
- String nodeString = n->nodeValue(); | |
- int pos = regExp->searchRev(nodeString); | |
- if (pos >= 0) | |
- return nodeString.substring(pos, regExp->matchedLength()); | |
- } | |
- } | |
- } | |
- } | |
- } | |
- // Any reason in practice to search all cells in that are above cell? | |
- return String(); | |
-} | |
- | |
-String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element) | |
-{ | |
- OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels)); | |
- // We stop searching after we've seen this many chars | |
- const unsigned int charsSearchedThreshold = 500; | |
- // This is the absolute max we search. We allow a little more slop than | |
- // charsSearchedThreshold, to make it more likely that we'll search whole nodes. | |
- const unsigned int maxCharsSearched = 600; | |
- // If the starting element is within a table, the cell that contains it | |
- HTMLTableCellElement* startingTableCell = 0; | |
- bool searchedCellAbove = false; | |
- | |
- // walk backwards in the node tree, until another element, or form, or end of tree | |
- int unsigned lengthSearched = 0; | |
- Node* n; | |
- for (n = element->traversePreviousNode(); | |
- n && lengthSearched < charsSearchedThreshold; | |
- n = n->traversePreviousNode()) | |
- { | |
- if (n->hasTagName(formTag) | |
- || (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement())) | |
- { | |
- // We hit another form element or the start of the form - bail out | |
- break; | |
- } else if (n->hasTagName(tdTag) && !startingTableCell) { | |
- startingTableCell = static_cast<HTMLTableCellElement*>(n); | |
- } else if (n->hasTagName(trTag) && startingTableCell) { | |
- String result = searchForLabelsAboveCell(regExp.get(), startingTableCell); | |
- if (!result.isEmpty()) | |
- return result; | |
- searchedCellAbove = true; | |
- } else if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) { | |
- // For each text chunk, run the regexp | |
- String nodeString = n->nodeValue(); | |
- // add 100 for slop, to make it more likely that we'll search whole nodes | |
- if (lengthSearched + nodeString.length() > maxCharsSearched) | |
- nodeString = nodeString.right(charsSearchedThreshold - lengthSearched); | |
- int pos = regExp->searchRev(nodeString); | |
- if (pos >= 0) | |
- return nodeString.substring(pos, regExp->matchedLength()); | |
- lengthSearched += nodeString.length(); | |
- } | |
- } | |
- | |
- // If we started in a cell, but bailed because we found the start of the form or the | |
- // previous element, we still might need to search the row above us for a label. | |
- if (startingTableCell && !searchedCellAbove) | |
- return searchForLabelsAboveCell(regExp.get(), startingTableCell); | |
- return String(); | |
-} | |
- | |
-String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element) | |
-{ | |
- String name = element->getAttribute(nameAttr); | |
- if (name.isEmpty()) | |
- return String(); | |
- | |
- // Make numbers and _'s in field names behave like word boundaries, e.g., "address2" | |
- replace(name, RegularExpression("\\d", TextCaseSensitive), " "); | |
- name.replace('_', ' '); | |
- | |
- OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels)); | |
- // Use the largest match we can find in the whole name string | |
- int pos; | |
- int length; | |
- int bestPos = -1; | |
- int bestLength = -1; | |
- int start = 0; | |
- do { | |
- pos = regExp->match(name, start); | |
- if (pos != -1) { | |
- length = regExp->matchedLength(); | |
- if (length >= bestLength) { | |
- bestPos = pos; | |
- bestLength = length; | |
- } | |
- start = pos + 1; | |
- } | |
- } while (pos != -1); | |
- | |
- if (bestPos != -1) | |
- return name.substring(bestPos, bestLength); | |
- return String(); | |
-} | |
- | |
-const VisibleSelection& Frame::mark() const | |
-{ | |
- return m_mark; | |
-} | |
- | |
-void Frame::setMark(const VisibleSelection& s) | |
-{ | |
- ASSERT(!s.base().node() || s.base().node()->document() == document()); | |
- ASSERT(!s.extent().node() || s.extent().node()->document() == document()); | |
- ASSERT(!s.start().node() || s.start().node()->document() == document()); | |
- ASSERT(!s.end().node() || s.end().node()->document() == document()); | |
- | |
- m_mark = s; | |
-} | |
- | |
-void Frame::notifyRendererOfSelectionChange(bool userTriggered) | |
-{ | |
- RenderObject* renderer = 0; | |
- if (selection()->rootEditableElement()) | |
- renderer = selection()->rootEditableElement()->shadowAncestorNode()->renderer(); | |
- | |
- // If the current selection is in a textfield or textarea, notify the renderer that the selection has changed | |
- if (renderer && renderer->isTextControl()) | |
- toRenderTextControl(renderer)->selectionChanged(userTriggered); | |
-} | |
- | |
-void Frame::setCaretVisible(bool flag) | |
-{ | |
- if (m_caretVisible == flag) | |
- return; | |
- clearCaretRectIfNeeded(); | |
- m_caretVisible = flag; | |
- selectionLayoutChanged(); | |
-} | |
- | |
-void Frame::clearCaretRectIfNeeded() | |
-{ | |
-#if ENABLE(TEXT_CARET) | |
- if (m_caretPaint) { | |
- m_caretPaint = false; | |
- selection()->invalidateCaretRect(); | |
- } | |
-#endif | |
-} | |
- | |
-// Helper function that tells whether a particular node is an element that has an entire | |
-// Frame and FrameView, a <frame>, <iframe>, or <object>. | |
-static bool isFrameElement(const Node *n) | |
-{ | |
- if (!n) | |
- return false; | |
- RenderObject *renderer = n->renderer(); | |
- if (!renderer || !renderer->isWidget()) | |
- return false; | |
- Widget* widget = toRenderWidget(renderer)->widget(); | |
- return widget && widget->isFrameView(); | |
-} | |
- | |
-void Frame::setFocusedNodeIfNeeded() | |
-{ | |
- if (selection()->isNone() || !selection()->isFocused()) | |
- return; | |
- | |
- bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); | |
- if (caretBrowsing) { | |
- Node* anchor = enclosingAnchorElement(selection()->base()); | |
- if (anchor) { | |
- page()->focusController()->setFocusedNode(anchor, this); | |
- return; | |
- } | |
- } | |
- | |
- Node* target = selection()->rootEditableElement(); | |
- if (target) { | |
- RenderObject* renderer = target->renderer(); | |
- | |
- // Walk up the render tree to search for a node to focus. | |
- // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields. | |
- while (renderer) { | |
- // We don't want to set focus on a subframe when selecting in a parent frame, | |
- // so add the !isFrameElement check here. There's probably a better way to make this | |
- // work in the long term, but this is the safest fix at this time. | |
- if (target && target->isMouseFocusable() && !isFrameElement(target)) { | |
- page()->focusController()->setFocusedNode(target, this); | |
- return; | |
- } | |
- renderer = renderer->parent(); | |
- if (renderer) | |
- target = renderer->node(); | |
- } | |
- document()->setFocusedNode(0); | |
- } | |
- | |
- if (caretBrowsing) | |
- page()->focusController()->setFocusedNode(0, this); | |
-} | |
- | |
-void Frame::selectionLayoutChanged() | |
-{ | |
- bool caretRectChanged = selection()->recomputeCaretRect(); | |
- | |
-#if ENABLE(TEXT_CARET) | |
- bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); | |
- bool shouldBlink = m_caretVisible | |
- && selection()->isCaret() && (selection()->isContentEditable() || caretBrowsing); | |
- | |
- // If the caret moved, stop the blink timer so we can restart with a | |
- // black caret in the new location. | |
- if (caretRectChanged || !shouldBlink) | |
- m_caretBlinkTimer.stop(); | |
- | |
- // Start blinking with a black caret. Be sure not to restart if we're | |
- // already blinking in the right location. | |
- if (shouldBlink && !m_caretBlinkTimer.isActive()) { | |
- if (double blinkInterval = page()->theme()->caretBlinkInterval()) | |
- m_caretBlinkTimer.startRepeating(blinkInterval); | |
- | |
- if (!m_caretPaint) { | |
- m_caretPaint = true; | |
- selection()->invalidateCaretRect(); | |
- } | |
- } | |
-#else | |
- if (!caretRectChanged) | |
- return; | |
-#endif | |
- | |
-#if 1 | |
- // added at webkit.org trunk r62873 (the fix is modified for this revision) | |
+/* | |
+ * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> | |
+ * 1999 Lars Knoll <knoll@kde.org> | |
+ * 1999 Antti Koivisto <koivisto@kde.org> | |
+ * 2000 Simon Hausmann <hausmann@kde.org> | |
+ * 2000 Stefan Schimanski <1Stein@gmx.de> | |
+ * 2001 George Staikos <staikos@kde.org> | |
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. | |
+ * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com> | |
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | |
+ * Copyright (C) 2008 Eric Seidel <eric@webkit.org> | |
+ * Copyright (c) 2010 ACCESS CO., LTD. All rights reserved. | |
+ * | |
+ * This library is free software; you can redistribute it and/or | |
+ * modify it under the terms of the GNU Library General Public | |
+ * License as published by the Free Software Foundation; either | |
+ * version 2 of the License, or (at your option) any later version. | |
+ * | |
+ * This library is distributed in the hope that it will be useful, | |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
+ * Library General Public License for more details. | |
+ * | |
+ * You should have received a copy of the GNU Library General Public License | |
+ * along with this library; see the file COPYING.LIB. If not, write to | |
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
+ * Boston, MA 02110-1301, USA. | |
+ */ | |
+ | |
+#include "config.h" | |
+#include "Frame.h" | |
+ | |
+#include "ApplyStyleCommand.h" | |
+#include "BeforeUnloadEvent.h" | |
+#include "CSSComputedStyleDeclaration.h" | |
+#include "CSSMutableStyleDeclaration.h" | |
+#include "CSSProperty.h" | |
+#include "CSSPropertyNames.h" | |
+#include "CachedCSSStyleSheet.h" | |
+#include "Chrome.h" | |
+#include "DOMWindow.h" | |
+#include "DocLoader.h" | |
+#include "DocumentType.h" | |
+#include "EditingText.h" | |
+#include "EditorClient.h" | |
+#include "EventNames.h" | |
+#include "FloatQuad.h" | |
+#include "FocusController.h" | |
+#include "FrameLoader.h" | |
+#include "FrameLoaderClient.h" | |
+#include "FrameView.h" | |
+#include "GraphicsContext.h" | |
+#include "HTMLDocument.h" | |
+#include "HTMLFormControlElement.h" | |
+#include "HTMLFormElement.h" | |
+#include "HTMLFrameElementBase.h" | |
+#include "HTMLNames.h" | |
+#include "HTMLTableCellElement.h" | |
+#include "HitTestResult.h" | |
+#include "Logging.h" | |
+#include "MediaFeatureNames.h" | |
+#include "Navigator.h" | |
+#include "NodeList.h" | |
+#include "Page.h" | |
+#include "PageGroup.h" | |
+#include "RegularExpression.h" | |
+#include "RenderPart.h" | |
+#include "RenderTableCell.h" | |
+#include "RenderTextControl.h" | |
+#include "RenderTheme.h" | |
+#include "RenderView.h" | |
+#include "ScriptController.h" | |
+#include "ScriptSourceCode.h" | |
+#include "ScriptValue.h" | |
+#include "Settings.h" | |
+#include "TextIterator.h" | |
+#include "TextResourceDecoder.h" | |
+#include "UserContentURLPattern.h" | |
+#include "XMLNames.h" | |
+#include "htmlediting.h" | |
+#include "markup.h" | |
+#include "npruntime_impl.h" | |
+#include "visible_units.h" | |
+#include <wtf/RefCountedLeakCounter.h> | |
+#include <wtf/StdLibExtras.h> | |
+ | |
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) | |
+#import <Carbon/Carbon.h> | |
+#endif | |
+ | |
+#if USE(JSC) | |
+#include "JSDOMWindowShell.h" | |
+#include "runtime_root.h" | |
+#endif | |
+ | |
+#if ENABLE(SVG) | |
+#include "SVGDocument.h" | |
+#include "SVGDocumentExtensions.h" | |
+#include "SVGNames.h" | |
+#include "XLinkNames.h" | |
+#endif | |
+ | |
+#if ENABLE(WML) | |
+#include "WMLNames.h" | |
+#endif | |
+ | |
+#if ENABLE(MATHML) | |
+#include "MathMLNames.h" | |
+#endif | |
+ | |
+using namespace std; | |
+ | |
+namespace WebCore { | |
+ | |
+using namespace HTMLNames; | |
+ | |
+#ifndef NDEBUG | |
+#if PLATFORM(WKC) | |
+static WTF::RefCountedLeakCounter* gFrameCounter = 0; | |
+#else | |
+static WTF::RefCountedLeakCounter frameCounter("Frame"); | |
+#endif | |
+#endif | |
+ | |
+static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement) | |
+{ | |
+ if (!ownerElement) | |
+ return 0; | |
+ return ownerElement->document()->frame(); | |
+} | |
+ | |
+Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* frameLoaderClient) | |
+ : m_page(page) | |
+ , m_treeNode(this, parentFromOwnerElement(ownerElement)) | |
+ , m_loader(this, frameLoaderClient) | |
+ , m_redirectScheduler(this) | |
+ , m_ownerElement(ownerElement) | |
+ , m_script(this) | |
+ , m_selectionGranularity(CharacterGranularity) | |
+ , m_selectionController(this) | |
+ , m_caretBlinkTimer(this, &Frame::caretBlinkTimerFired) | |
+ , m_editor(this) | |
+ , m_eventHandler(this) | |
+ , m_animationController(this) | |
+ , m_lifeSupportTimer(this, &Frame::lifeSupportTimerFired) | |
+#if ENABLE(ORIENTATION_EVENTS) | |
+ , m_orientation(0) | |
+#endif | |
+ , m_caretVisible(false) | |
+ , m_caretPaint(true) | |
+ , m_highlightTextMatches(false) | |
+ , m_inViewSourceMode(false) | |
+ , m_needsReapplyStyles(false) | |
+ , m_isDisconnected(false) | |
+ , m_excludeFromTextSearch(false) | |
+{ | |
+ Frame* parent = parentFromOwnerElement(ownerElement); | |
+ m_zoomFactor = parent ? parent->m_zoomFactor : 1.0f; | |
+ | |
+ AtomicString::init(); | |
+ HTMLNames::init(); | |
+ QualifiedName::init(); | |
+ MediaFeatureNames::init(); | |
+ | |
+#if ENABLE(SVG) | |
+ SVGNames::init(); | |
+ XLinkNames::init(); | |
+#endif | |
+ | |
+#if ENABLE(WML) | |
+ WMLNames::init(); | |
+#endif | |
+ | |
+#if ENABLE(MATHML) | |
+ MathMLNames::init(); | |
+#endif | |
+ | |
+ XMLNames::init(); | |
+ | |
+ if (!ownerElement) | |
+ page->setMainFrame(this); | |
+ else { | |
+ page->incrementFrameCount(); | |
+ // Make sure we will not end up with two frames referencing the same owner element. | |
+ ASSERT((!(ownerElement->m_contentFrame)) || (ownerElement->m_contentFrame->ownerElement() != ownerElement)); | |
+ ownerElement->m_contentFrame = this; | |
+ } | |
+ | |
+#ifndef NDEBUG | |
+#if PLATFORM(WKC) | |
+ if (!gFrameCounter) { | |
+ gFrameCounter = new WTF::RefCountedLeakCounter("Frame"); | |
+ } | |
+ WTF::RefCountedLeakCounter& frameCounter = *gFrameCounter; | |
+#endif | |
+ frameCounter.increment(); | |
+#endif | |
+} | |
+ | |
+Frame::~Frame() | |
+{ | |
+ setView(0); | |
+ loader()->cancelAndClear(); | |
+ | |
+ // FIXME: We should not be doing all this work inside the destructor | |
+ | |
+ ASSERT(!m_lifeSupportTimer.isActive()); | |
+ | |
+#ifndef NDEBUG | |
+#if PLATFORM(WKC) | |
+ WTF::RefCountedLeakCounter& frameCounter = *gFrameCounter; | |
+#endif | |
+ frameCounter.decrement(); | |
+#endif | |
+ | |
+ disconnectOwnerElement(); | |
+ | |
+ if (m_domWindow) | |
+ m_domWindow->disconnectFrame(); | |
+ script()->clearWindowShell(); | |
+ | |
+ HashSet<DOMWindow*>::iterator end = m_liveFormerWindows.end(); | |
+ for (HashSet<DOMWindow*>::iterator it = m_liveFormerWindows.begin(); it != end; ++it) | |
+ (*it)->disconnectFrame(); | |
+ | |
+ if (m_view) { | |
+ m_view->hide(); | |
+ m_view->clearFrame(); | |
+ } | |
+ | |
+ ASSERT(!m_lifeSupportTimer.isActive()); | |
+} | |
+ | |
+void Frame::init() | |
+{ | |
+ m_loader.init(); | |
+} | |
+ | |
+FrameLoader* Frame::loader() const | |
+{ | |
+ return &m_loader; | |
+} | |
+ | |
+RedirectScheduler* Frame::redirectScheduler() const | |
+{ | |
+ return &m_redirectScheduler; | |
+} | |
+ | |
+FrameView* Frame::view() const | |
+{ | |
+ return m_view.get(); | |
+} | |
+ | |
+void Frame::setView(PassRefPtr<FrameView> view) | |
+{ | |
+ // We the custom scroll bars as early as possible to prevent m_doc->detach() | |
+ // from messing with the view such that its scroll bars won't be torn down. | |
+ // FIXME: We should revisit this. | |
+ if (m_view) | |
+ m_view->detachCustomScrollbars(); | |
+ | |
+ // Detach the document now, so any onUnload handlers get run - if | |
+ // we wait until the view is destroyed, then things won't be | |
+ // hooked up enough for some JavaScript calls to work. | |
+ if (!view && m_doc && m_doc->attached() && !m_doc->inPageCache()) { | |
+ // FIXME: We don't call willRemove here. Why is that OK? | |
+ m_doc->detach(); | |
+ if (m_view) | |
+ m_view->unscheduleRelayout(); | |
+ } | |
+ eventHandler()->clear(); | |
+ | |
+ m_view = view; | |
+ | |
+ // Only one form submission is allowed per view of a part. | |
+ // Since this part may be getting reused as a result of being | |
+ // pulled from the back/forward cache, reset this flag. | |
+ loader()->resetMultipleFormSubmissionProtection(); | |
+} | |
+ | |
+ScriptController* Frame::script() | |
+{ | |
+ return &m_script; | |
+} | |
+ | |
+Document* Frame::document() const | |
+{ | |
+ return m_doc.get(); | |
+} | |
+ | |
+void Frame::setDocument(PassRefPtr<Document> newDoc) | |
+{ | |
+ if (m_doc && m_doc->attached() && !m_doc->inPageCache()) { | |
+ // FIXME: We don't call willRemove here. Why is that OK? | |
+ m_doc->detach(); | |
+ } | |
+ | |
+ m_doc = newDoc; | |
+ if (m_doc && selection()->isFocusedAndActive()) | |
+ setUseSecureKeyboardEntry(m_doc->useSecureKeyboardEntryWhenActive()); | |
+ | |
+ if (m_doc && !m_doc->attached()) | |
+ m_doc->attach(); | |
+ | |
+ // Update the cached 'document' property, which is now stale. | |
+ m_script.updateDocument(); | |
+} | |
+ | |
+#if ENABLE(ORIENTATION_EVENTS) | |
+void Frame::sendOrientationChangeEvent(int orientation) | |
+{ | |
+ m_orientation = orientation; | |
+ if (Document* doc = document()) | |
+ doc->dispatchWindowEvent(Event::create(eventNames().orientationchangeEvent, false, false)); | |
+} | |
+#endif // ENABLE(ORIENTATION_EVENTS) | |
+ | |
+Settings* Frame::settings() const | |
+{ | |
+ return m_page ? m_page->settings() : 0; | |
+} | |
+ | |
+String Frame::selectedText() const | |
+{ | |
+ return plainText(selection()->toNormalizedRange().get()); | |
+} | |
+ | |
+IntRect Frame::firstRectForRange(Range* range) const | |
+{ | |
+ int extraWidthToEndOfLine = 0; | |
+ ExceptionCode ec = 0; | |
+ ASSERT(range->startContainer(ec)); | |
+ ASSERT(range->endContainer(ec)); | |
+ | |
+ InlineBox* startInlineBox; | |
+ int startCaretOffset; | |
+ range->startPosition().getInlineBoxAndOffset(DOWNSTREAM, startInlineBox, startCaretOffset); | |
+ | |
+ RenderObject* startRenderer = range->startContainer(ec)->renderer(); | |
+ IntRect startCaretRect = startRenderer->localCaretRect(startInlineBox, startCaretOffset, &extraWidthToEndOfLine); | |
+ if (startCaretRect != IntRect()) | |
+ startCaretRect = startRenderer->localToAbsoluteQuad(FloatRect(startCaretRect)).enclosingBoundingBox(); | |
+ | |
+ InlineBox* endInlineBox; | |
+ int endCaretOffset; | |
+ range->endPosition().getInlineBoxAndOffset(UPSTREAM, endInlineBox, endCaretOffset); | |
+ | |
+ RenderObject* endRenderer = range->endContainer(ec)->renderer(); | |
+ IntRect endCaretRect = endRenderer->localCaretRect(endInlineBox, endCaretOffset); | |
+ if (endCaretRect != IntRect()) | |
+ endCaretRect = endRenderer->localToAbsoluteQuad(FloatRect(endCaretRect)).enclosingBoundingBox(); | |
+ | |
+ if (startCaretRect.y() == endCaretRect.y()) { | |
+ // start and end are on the same line | |
+ return IntRect(min(startCaretRect.x(), endCaretRect.x()), | |
+ startCaretRect.y(), | |
+ abs(endCaretRect.x() - startCaretRect.x()), | |
+ max(startCaretRect.height(), endCaretRect.height())); | |
+ } | |
+ | |
+ // start and end aren't on the same line, so go from start to the end of its line | |
+ return IntRect(startCaretRect.x(), | |
+ startCaretRect.y(), | |
+ startCaretRect.width() + extraWidthToEndOfLine, | |
+ startCaretRect.height()); | |
+} | |
+ | |
+SelectionController* Frame::selection() const | |
+{ | |
+ return &m_selectionController; | |
+} | |
+ | |
+Editor* Frame::editor() const | |
+{ | |
+ return &m_editor; | |
+} | |
+ | |
+TextGranularity Frame::selectionGranularity() const | |
+{ | |
+ return m_selectionGranularity; | |
+} | |
+ | |
+void Frame::setSelectionGranularity(TextGranularity granularity) | |
+{ | |
+ m_selectionGranularity = granularity; | |
+} | |
+ | |
+SelectionController* Frame::dragCaretController() const | |
+{ | |
+ return m_page->dragCaretController(); | |
+} | |
+ | |
+ | |
+AnimationController* Frame::animation() const | |
+{ | |
+ return &m_animationController; | |
+} | |
+ | |
+#if PLATFORM(WKC) | |
+static RegularExpression* gWordRegExp = 0; | |
+#endif | |
+ | |
+static RegularExpression* createRegExpForLabels(const Vector<String>& labels) | |
+{ | |
+ // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being | |
+ // the same across calls. We can't do that. | |
+ | |
+#if PLATFORM(WKC) | |
+ if (!gWordRegExp) { | |
+ gWordRegExp = new RegularExpression("\\w", TextCaseSensitive); | |
+ } | |
+ RegularExpression& wordRegExp = *gWordRegExp; | |
+#else | |
+ DEFINE_STATIC_LOCAL(RegularExpression, wordRegExp, ("\\w", TextCaseSensitive)); | |
+#endif | |
+ String pattern("("); | |
+ unsigned int numLabels = labels.size(); | |
+ unsigned int i; | |
+ for (i = 0; i < numLabels; i++) { | |
+ String label = labels[i]; | |
+ | |
+ bool startsWithWordChar = false; | |
+ bool endsWithWordChar = false; | |
+ if (label.length()) { | |
+ startsWithWordChar = wordRegExp.match(label.substring(0, 1)) >= 0; | |
+ endsWithWordChar = wordRegExp.match(label.substring(label.length() - 1, 1)) >= 0; | |
+ } | |
+ | |
+ if (i) | |
+ pattern.append("|"); | |
+ // Search for word boundaries only if label starts/ends with "word characters". | |
+ // If we always searched for word boundaries, this wouldn't work for languages | |
+ // such as Japanese. | |
+ if (startsWithWordChar) | |
+ pattern.append("\\b"); | |
+ pattern.append(label); | |
+ if (endsWithWordChar) | |
+ pattern.append("\\b"); | |
+ } | |
+ pattern.append(")"); | |
+ return new RegularExpression(pattern, TextCaseInsensitive); | |
+} | |
+ | |
+String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell) | |
+{ | |
+ RenderObject* cellRenderer = cell->renderer(); | |
+ | |
+ if (cellRenderer && cellRenderer->isTableCell()) { | |
+ RenderTableCell* tableCellRenderer = toRenderTableCell(cellRenderer); | |
+ RenderTableCell* cellAboveRenderer = tableCellRenderer->table()->cellAbove(tableCellRenderer); | |
+ | |
+ if (cellAboveRenderer) { | |
+ HTMLTableCellElement* aboveCell = | |
+ static_cast<HTMLTableCellElement*>(cellAboveRenderer->node()); | |
+ | |
+ if (aboveCell) { | |
+ // search within the above cell we found for a match | |
+ for (Node* n = aboveCell->firstChild(); n; n = n->traverseNextNode(aboveCell)) { | |
+ if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) { | |
+ // For each text chunk, run the regexp | |
+ String nodeString = n->nodeValue(); | |
+ int pos = regExp->searchRev(nodeString); | |
+ if (pos >= 0) | |
+ return nodeString.substring(pos, regExp->matchedLength()); | |
+ } | |
+ } | |
+ } | |
+ } | |
+ } | |
+ // Any reason in practice to search all cells in that are above cell? | |
+ return String(); | |
+} | |
+ | |
+String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element) | |
+{ | |
+ OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels)); | |
+ // We stop searching after we've seen this many chars | |
+ const unsigned int charsSearchedThreshold = 500; | |
+ // This is the absolute max we search. We allow a little more slop than | |
+ // charsSearchedThreshold, to make it more likely that we'll search whole nodes. | |
+ const unsigned int maxCharsSearched = 600; | |
+ // If the starting element is within a table, the cell that contains it | |
+ HTMLTableCellElement* startingTableCell = 0; | |
+ bool searchedCellAbove = false; | |
+ | |
+ // walk backwards in the node tree, until another element, or form, or end of tree | |
+ int unsigned lengthSearched = 0; | |
+ Node* n; | |
+ for (n = element->traversePreviousNode(); | |
+ n && lengthSearched < charsSearchedThreshold; | |
+ n = n->traversePreviousNode()) | |
+ { | |
+ if (n->hasTagName(formTag) | |
+ || (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement())) | |
+ { | |
+ // We hit another form element or the start of the form - bail out | |
+ break; | |
+ } else if (n->hasTagName(tdTag) && !startingTableCell) { | |
+ startingTableCell = static_cast<HTMLTableCellElement*>(n); | |
+ } else if (n->hasTagName(trTag) && startingTableCell) { | |
+ String result = searchForLabelsAboveCell(regExp.get(), startingTableCell); | |
+ if (!result.isEmpty()) | |
+ return result; | |
+ searchedCellAbove = true; | |
+ } else if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) { | |
+ // For each text chunk, run the regexp | |
+ String nodeString = n->nodeValue(); | |
+ // add 100 for slop, to make it more likely that we'll search whole nodes | |
+ if (lengthSearched + nodeString.length() > maxCharsSearched) | |
+ nodeString = nodeString.right(charsSearchedThreshold - lengthSearched); | |
+ int pos = regExp->searchRev(nodeString); | |
+ if (pos >= 0) | |
+ return nodeString.substring(pos, regExp->matchedLength()); | |
+ lengthSearched += nodeString.length(); | |
+ } | |
+ } | |
+ | |
+ // If we started in a cell, but bailed because we found the start of the form or the | |
+ // previous element, we still might need to search the row above us for a label. | |
+ if (startingTableCell && !searchedCellAbove) | |
+ return searchForLabelsAboveCell(regExp.get(), startingTableCell); | |
+ return String(); | |
+} | |
+ | |
+String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element) | |
+{ | |
+ String name = element->getAttribute(nameAttr); | |
+ if (name.isEmpty()) | |
+ return String(); | |
+ | |
+ // Make numbers and _'s in field names behave like word boundaries, e.g., "address2" | |
+ replace(name, RegularExpression("\\d", TextCaseSensitive), " "); | |
+ name.replace('_', ' '); | |
+ | |
+ OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels)); | |
+ // Use the largest match we can find in the whole name string | |
+ int pos; | |
+ int length; | |
+ int bestPos = -1; | |
+ int bestLength = -1; | |
+ int start = 0; | |
+ do { | |
+ pos = regExp->match(name, start); | |
+ if (pos != -1) { | |
+ length = regExp->matchedLength(); | |
+ if (length >= bestLength) { | |
+ bestPos = pos; | |
+ bestLength = length; | |
+ } | |
+ start = pos + 1; | |
+ } | |
+ } while (pos != -1); | |
+ | |
+ if (bestPos != -1) | |
+ return name.substring(bestPos, bestLength); | |
+ return String(); | |
+} | |
+ | |
+const VisibleSelection& Frame::mark() const | |
+{ | |
+ return m_mark; | |
+} | |
+ | |
+void Frame::setMark(const VisibleSelection& s) | |
+{ | |
+ ASSERT(!s.base().node() || s.base().node()->document() == document()); | |
+ ASSERT(!s.extent().node() || s.extent().node()->document() == document()); | |
+ ASSERT(!s.start().node() || s.start().node()->document() == document()); | |
+ ASSERT(!s.end().node() || s.end().node()->document() == document()); | |
+ | |
+ m_mark = s; | |
+} | |
+ | |
+void Frame::notifyRendererOfSelectionChange(bool userTriggered) | |
+{ | |
+ RenderObject* renderer = 0; | |
+ if (selection()->rootEditableElement()) | |
+ renderer = selection()->rootEditableElement()->shadowAncestorNode()->renderer(); | |
+ | |
+ // If the current selection is in a textfield or textarea, notify the renderer that the selection has changed | |
+ if (renderer && renderer->isTextControl()) | |
+ toRenderTextControl(renderer)->selectionChanged(userTriggered); | |
+} | |
+ | |
+void Frame::setCaretVisible(bool flag) | |
+{ | |
+ if (m_caretVisible == flag) | |
+ return; | |
+ clearCaretRectIfNeeded(); | |
+ m_caretVisible = flag; | |
+ selection()->setNeedsDisplayUpdate(); | |
+} | |
+ | |
+void Frame::clearCaretRectIfNeeded() | |
+{ | |
+#if ENABLE(TEXT_CARET) | |
+ if (m_caretPaint) { | |
+ m_caretPaint = false; | |
+ selection()->invalidateCaretRect(); | |
+ } | |
+#endif | |
+} | |
+ | |
+// Helper function that tells whether a particular node is an element that has an entire | |
+// Frame and FrameView, a <frame>, <iframe>, or <object>. | |
+static bool isFrameElement(const Node *n) | |
+{ | |
+ if (!n) | |
+ return false; | |
+ RenderObject *renderer = n->renderer(); | |
+ if (!renderer || !renderer->isWidget()) | |
+ return false; | |
+ Widget* widget = toRenderWidget(renderer)->widget(); | |
+ return widget && widget->isFrameView(); | |
+} | |
+ | |
+void Frame::setFocusedNodeIfNeeded() | |
+{ | |
+ if (selection()->isNone() || !selection()->isFocused()) | |
+ return; | |
+ | |
+ bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); | |
+ if (caretBrowsing) { | |
+ Node* anchor = enclosingAnchorElement(selection()->base()); | |
+ if (anchor) { | |
+ page()->focusController()->setFocusedNode(anchor, this); | |
+ return; | |
+ } | |
+ } | |
+ | |
+ Node* target = selection()->rootEditableElement(); | |
+ if (target) { | |
+ RenderObject* renderer = target->renderer(); | |
+ | |
+ // Walk up the render tree to search for a node to focus. | |
+ // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields. | |
+ while (renderer) { | |
+ // We don't want to set focus on a subframe when selecting in a parent frame, | |
+ // so add the !isFrameElement check here. There's probably a better way to make this | |
+ // work in the long term, but this is the safest fix at this time. | |
+ if (target && target->isMouseFocusable() && !isFrameElement(target)) { | |
+ page()->focusController()->setFocusedNode(target, this); | |
+ return; | |
+ } | |
+ renderer = renderer->parent(); | |
+ if (renderer) | |
+ target = renderer->node(); | |
+ } | |
+ document()->setFocusedNode(0); | |
+ } | |
+ | |
+ if (caretBrowsing) | |
+ page()->focusController()->setFocusedNode(0, this); | |
+} | |
+ | |
+#if PLATFORM(WKC) | |
+static bool gAlreadyInSelectionLayoutChanged; | |
+#endif | |
+ | |
+void Frame::selectionLayoutChanged() | |
+{ | |
+ selection()->setNeedsDisplayUpdate(false); | |
+ | |
+#if ENABLE(TEXT_CARET) | |
+ if (gAlreadyInSelectionLayoutChanged) | |
+ return; | |
+ | |
+ gAlreadyInSelectionLayoutChanged = true; | |
+ | |
+ bool caretRectChanged = selection()->recomputeCaretRect(); | |
+ | |
+ bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); | |
+ bool shouldBlink = m_caretVisible | |
+ && selection()->isCaret() && (selection()->isContentEditable() || caretBrowsing); | |
+ | |
+ // If the caret moved, stop the blink timer so we can restart with a | |
+ // black caret in the new location. | |
+ if (caretRectChanged || !shouldBlink) | |
+ m_caretBlinkTimer.stop(); | |
+ | |
+ // Start blinking with a black caret. Be sure not to restart if we're | |
+ // already blinking in the right location. | |
+ if (shouldBlink && !m_caretBlinkTimer.isActive()) { | |
+ if (double blinkInterval = page()->theme()->caretBlinkInterval()) | |
+ m_caretBlinkTimer.startRepeating(blinkInterval); | |
+ | |
+ if (!m_caretPaint) { | |
+ m_caretPaint = true; | |
+ selection()->invalidateCaretRect(); | |
+ } | |
+ } | |
+ gAlreadyInSelectionLayoutChanged = false; | |
+#endif | |
+ | |
+#if 1 | |
+ // added at webkit.org trunk r62873 (the fix is modified for this revision) | |
// We need to update style in case the node containing the selection is made display:none. | |
- document()->updateStyleIfNeeded(); | |
-#endif | |
- | |
- RenderView* view = contentRenderer(); | |
- if (!view) | |
- return; | |
- | |
- VisibleSelection selection = this->selection()->selection(); | |
- | |
- if (!selection.isRange()) | |
- view->clearSelection(); | |
- else { | |
- // Use the rightmost candidate for the start of the selection, and the leftmost candidate for the end of the selection. | |
- // Example: foo <a>bar</a>. Imagine that a line wrap occurs after 'foo', and that 'bar' is selected. If we pass [foo, 3] | |
- // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected | |
- // and will fill the gap before 'bar'. | |
- Position startPos = selection.start(); | |
- if (startPos.downstream().isCandidate()) | |
- startPos = startPos.downstream(); | |
- Position endPos = selection.end(); | |
- if (endPos.upstream().isCandidate()) | |
- endPos = endPos.upstream(); | |
- | |
- // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted | |
- // because we don't yet notify the SelectionController of text removal. | |
- if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) { | |
- RenderObject *startRenderer = startPos.node()->renderer(); | |
- RenderObject *endRenderer = endPos.node()->renderer(); | |
- view->setSelection(startRenderer, startPos.deprecatedEditingOffset(), endRenderer, endPos.deprecatedEditingOffset()); | |
- } | |
- } | |
-} | |
- | |
-void Frame::caretBlinkTimerFired(Timer<Frame>*) | |
-{ | |
-#if ENABLE(TEXT_CARET) | |
- ASSERT(m_caretVisible); | |
- ASSERT(selection()->isCaret()); | |
- bool caretPaint = m_caretPaint; | |
- if (selection()->isCaretBlinkingSuspended() && caretPaint) | |
- return; | |
- m_caretPaint = !caretPaint; | |
- selection()->invalidateCaretRect(); | |
-#endif | |
-} | |
- | |
-void Frame::paintCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect) const | |
-{ | |
-#if ENABLE(TEXT_CARET) | |
- if (m_caretPaint && m_caretVisible) | |
- selection()->paintCaret(p, tx, ty, clipRect); | |
-#endif | |
-} | |
- | |
-void Frame::paintDragCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect) const | |
-{ | |
-#if ENABLE(TEXT_CARET) | |
- SelectionController* dragCaretController = m_page->dragCaretController(); | |
- ASSERT(dragCaretController->selection().isCaret()); | |
- if (dragCaretController->selection().start().node()->document()->frame() == this) | |
- dragCaretController->paintCaret(p, tx, ty, clipRect); | |
-#endif | |
-} | |
- | |
-float Frame::zoomFactor() const | |
-{ | |
- return m_zoomFactor; | |
-} | |
- | |
-bool Frame::isZoomFactorTextOnly() const | |
-{ | |
- return m_page->settings()->zoomsTextOnly(); | |
-} | |
- | |
-bool Frame::shouldApplyTextZoom() const | |
-{ | |
- if (m_zoomFactor == 1.0f || !isZoomFactorTextOnly()) | |
- return false; | |
-#if ENABLE(SVG) | |
- if (m_doc->isSVGDocument()) | |
- return false; | |
-#endif | |
- return true; | |
-} | |
- | |
-bool Frame::shouldApplyPageZoom() const | |
-{ | |
- if (m_zoomFactor == 1.0f || isZoomFactorTextOnly()) | |
- return false; | |
-#if ENABLE(SVG) | |
- if (m_doc->isSVGDocument()) | |
- return false; | |
-#endif | |
- return true; | |
-} | |
- | |
-void Frame::setZoomFactor(float percent, bool isTextOnly) | |
-{ | |
- if (m_zoomFactor == percent && isZoomFactorTextOnly() == isTextOnly) | |
- return; | |
- | |
-#if ENABLE(SVG) | |
- // SVG doesn't care if the zoom factor is text only. It will always apply a | |
- // zoom to the whole SVG. | |
- if (m_doc->isSVGDocument()) { | |
- if (!static_cast<SVGDocument*>(m_doc.get())->zoomAndPanEnabled()) | |
- return; | |
- m_zoomFactor = percent; | |
- m_page->settings()->setZoomsTextOnly(true); // We do this to avoid doing any scaling of CSS pixels, since the SVG has its own notion of zoom. | |
- if (m_doc->renderer()) | |
- m_doc->renderer()->repaint(); | |
- return; | |
- } | |
-#endif | |
- | |
- m_zoomFactor = percent; | |
- m_page->settings()->setZoomsTextOnly(isTextOnly); | |
- | |
- m_doc->recalcStyle(Node::Force); | |
- | |
- for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling()) | |
- child->setZoomFactor(m_zoomFactor, isTextOnly); | |
- | |
- if (m_doc->renderer() && m_doc->renderer()->needsLayout() && view()->didFirstLayout()) | |
- view()->layout(); | |
-} | |
- | |
-void Frame::setPrinting(bool printing, float minPageWidth, float maxPageWidth, bool adjustViewSize) | |
-{ | |
- m_doc->setPrinting(printing); | |
- view()->setMediaType(printing ? "print" : "screen"); | |
- m_doc->updateStyleSelector(); | |
- view()->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, adjustViewSize); | |
- | |
- for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling()) | |
- child->setPrinting(printing, minPageWidth, maxPageWidth, adjustViewSize); | |
-} | |
- | |
-void Frame::setJSStatusBarText(const String& text) | |
-{ | |
- ASSERT(m_doc); // Client calls shouldn't be made when the frame is in inconsistent state. | |
- m_kjsStatusBarText = text; | |
- if (m_page) | |
- m_page->chrome()->setStatusbarText(this, m_kjsStatusBarText); | |
-} | |
- | |
-void Frame::setJSDefaultStatusBarText(const String& text) | |
-{ | |
- ASSERT(m_doc); // Client calls shouldn't be made when the frame is in inconsistent state. | |
- m_kjsDefaultStatusBarText = text; | |
- if (m_page) | |
- m_page->chrome()->setStatusbarText(this, m_kjsDefaultStatusBarText); | |
-} | |
- | |
-String Frame::jsStatusBarText() const | |
-{ | |
- return m_kjsStatusBarText; | |
-} | |
- | |
-String Frame::jsDefaultStatusBarText() const | |
-{ | |
- return m_kjsDefaultStatusBarText; | |
-} | |
- | |
-void Frame::setNeedsReapplyStyles() | |
-{ | |
- // When the frame is not showing web content, it doesn't make sense to apply styles. | |
- // If we tried, we'd end up doing things with the document, but the document, if one | |
- // exists, is not currently shown and should be in the page cache. | |
- if (!m_loader.client()->hasHTMLView()) | |
- return; | |
- | |
- if (m_needsReapplyStyles) | |
- return; | |
- | |
- m_needsReapplyStyles = true; | |
- | |
- // FrameView's "layout" timer includes reapplyStyles, so despite its | |
- // name, it's what we want to call here. | |
- if (view()) | |
- view()->scheduleRelayout(); | |
-} | |
- | |
-bool Frame::needsReapplyStyles() const | |
-{ | |
- return m_needsReapplyStyles; | |
-} | |
- | |
-void Frame::reapplyStyles() | |
-{ | |
- m_needsReapplyStyles = false; | |
- | |
- // FIXME: This call doesn't really make sense in a function called reapplyStyles. | |
- // We should probably eventually move it into its own function. | |
- m_doc->docLoader()->setAutoLoadImages(m_page && m_page->settings()->loadsImagesAutomatically()); | |
- | |
- // FIXME: It's not entirely clear why the following is needed. | |
- // The document automatically does this as required when you set the style sheet. | |
- // But we had problems when this code was removed. Details are in | |
- // <http://bugs.webkit.org/show_bug.cgi?id=8079>. | |
- m_doc->updateStyleSelector(); | |
-} | |
- | |
-void Frame::injectUserScripts(UserScriptInjectionTime injectionTime) | |
-{ | |
- if (!m_page) | |
- return; | |
- | |
- // Walk the hashtable. Inject by world. | |
- const UserScriptMap* userScripts = m_page->group().userScripts(); | |
- if (!userScripts) | |
- return; | |
- UserScriptMap::const_iterator end = userScripts->end(); | |
- for (UserScriptMap::const_iterator it = userScripts->begin(); it != end; ++it) | |
- injectUserScriptsForWorld(it->first.get(), *it->second, injectionTime); | |
-} | |
- | |
-void Frame::injectUserScriptsForWorld(DOMWrapperWorld* world, const UserScriptVector& userScripts, UserScriptInjectionTime injectionTime) | |
-{ | |
- if (userScripts.isEmpty()) | |
- return; | |
- | |
- Document* doc = document(); | |
- if (!doc) | |
- return; | |
- | |
- Vector<ScriptSourceCode> sourceCode; | |
- unsigned count = userScripts.size(); | |
- for (unsigned i = 0; i < count; ++i) { | |
- UserScript* script = userScripts[i].get(); | |
- if (script->injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(doc->url(), script->whitelist(), script->blacklist())) | |
- m_script.evaluateInWorld(ScriptSourceCode(script->source(), script->url()), world); | |
- } | |
-} | |
- | |
-bool Frame::shouldChangeSelection(const VisibleSelection& newSelection) const | |
-{ | |
- return shouldChangeSelection(selection()->selection(), newSelection, newSelection.affinity(), false); | |
-} | |
- | |
-bool Frame::shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity affinity, bool stillSelecting) const | |
-{ | |
- return editor()->client()->shouldChangeSelectedRange(oldSelection.toNormalizedRange().get(), newSelection.toNormalizedRange().get(), | |
- affinity, stillSelecting); | |
-} | |
- | |
-bool Frame::shouldDeleteSelection(const VisibleSelection& selection) const | |
-{ | |
- return editor()->client()->shouldDeleteRange(selection.toNormalizedRange().get()); | |
-} | |
- | |
-bool Frame::isContentEditable() const | |
-{ | |
- if (m_editor.clientIsEditable()) | |
- return true; | |
- return m_doc->inDesignMode(); | |
-} | |
- | |
-#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) | |
-const short enableRomanKeyboardsOnly = -23; | |
-#endif | |
-void Frame::setUseSecureKeyboardEntry(bool enable) | |
-{ | |
-#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) | |
- if (enable == IsSecureEventInputEnabled()) | |
- return; | |
- if (enable) { | |
- EnableSecureEventInput(); | |
-#ifdef BUILDING_ON_TIGER | |
- KeyScript(enableRomanKeyboardsOnly); | |
-#else | |
- // WebKit substitutes nil for input context when in password field, which corresponds to null TSMDocument. So, there is | |
- // no need to call TSMGetActiveDocument(), which may return an incorrect result when selection hasn't been yet updated | |
- // after focusing a node. | |
- CFArrayRef inputSources = TISCreateASCIICapableInputSourceList(); | |
- TSMSetDocumentProperty(0, kTSMDocumentEnabledInputSourcesPropertyTag, sizeof(CFArrayRef), &inputSources); | |
- CFRelease(inputSources); | |
-#endif | |
- } else { | |
- DisableSecureEventInput(); | |
-#ifdef BUILDING_ON_TIGER | |
- KeyScript(smKeyEnableKybds); | |
-#else | |
- TSMRemoveDocumentProperty(0, kTSMDocumentEnabledInputSourcesPropertyTag); | |
-#endif | |
- } | |
-#endif | |
-} | |
- | |
-void Frame::updateSecureKeyboardEntryIfActive() | |
-{ | |
- if (selection()->isFocusedAndActive()) | |
- setUseSecureKeyboardEntry(m_doc->useSecureKeyboardEntryWhenActive()); | |
-} | |
- | |
-CSSMutableStyleDeclaration *Frame::typingStyle() const | |
-{ | |
- return m_typingStyle.get(); | |
-} | |
- | |
-void Frame::setTypingStyle(CSSMutableStyleDeclaration *style) | |
-{ | |
- m_typingStyle = style; | |
-} | |
- | |
-void Frame::clearTypingStyle() | |
-{ | |
- m_typingStyle = 0; | |
-} | |
- | |
-void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction) | |
-{ | |
- if (!style || !style->length()) { | |
- clearTypingStyle(); | |
- return; | |
- } | |
- | |
- // Calculate the current typing style. | |
- RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable(); | |
- if (typingStyle()) { | |
- typingStyle()->merge(mutableStyle.get()); | |
- mutableStyle = typingStyle(); | |
- } | |
- | |
- RefPtr<CSSValue> unicodeBidi; | |
- RefPtr<CSSValue> direction; | |
- if (editingAction == EditActionSetWritingDirection) { | |
- unicodeBidi = mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi); | |
- direction = mutableStyle->getPropertyCSSValue(CSSPropertyDirection); | |
- } | |
- | |
- Node* node = selection()->selection().visibleStart().deepEquivalent().node(); | |
- computedStyle(node)->diff(mutableStyle.get()); | |
- | |
- if (editingAction == EditActionSetWritingDirection && unicodeBidi) { | |
- ASSERT(unicodeBidi->isPrimitiveValue()); | |
- mutableStyle->setProperty(CSSPropertyUnicodeBidi, static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent()); | |
- if (direction) { | |
- ASSERT(direction->isPrimitiveValue()); | |
- mutableStyle->setProperty(CSSPropertyDirection, static_cast<CSSPrimitiveValue*>(direction.get())->getIdent()); | |
- } | |
- } | |
- | |
- // Handle block styles, substracting these from the typing style. | |
- RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties(); | |
- blockStyle->diff(mutableStyle.get()); | |
- if (blockStyle->length() > 0) | |
- applyCommand(ApplyStyleCommand::create(document(), blockStyle.get(), editingAction)); | |
- | |
- // Set the remaining style as the typing style. | |
- m_typingStyle = mutableStyle.release(); | |
-} | |
- | |
-String Frame::selectionStartStylePropertyValue(int stylePropertyID) const | |
-{ | |
- Node *nodeToRemove; | |
- RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove); | |
- if (!selectionStyle) | |
- return String(); | |
- | |
- String value = selectionStyle->getPropertyValue(stylePropertyID); | |
- | |
- if (nodeToRemove) { | |
- ExceptionCode ec = 0; | |
- nodeToRemove->remove(ec); | |
- ASSERT(!ec); | |
- } | |
- | |
- return value; | |
-} | |
- | |
-PassRefPtr<CSSComputedStyleDeclaration> Frame::selectionComputedStyle(Node*& nodeToRemove) const | |
-{ | |
- nodeToRemove = 0; | |
- | |
- if (selection()->isNone()) | |
- return 0; | |
- | |
- RefPtr<Range> range(selection()->toNormalizedRange()); | |
- Position pos = range->editingStartPosition(); | |
- | |
- Element *elem = pos.element(); | |
- if (!elem) | |
- return 0; | |
- | |
- RefPtr<Element> styleElement = elem; | |
- ExceptionCode ec = 0; | |
- | |
- if (m_typingStyle) { | |
- styleElement = document()->createElement(spanTag, false); | |
- | |
- styleElement->setAttribute(styleAttr, m_typingStyle->cssText().impl(), ec); | |
- ASSERT(!ec); | |
- | |
- styleElement->appendChild(document()->createEditingTextNode(""), ec); | |
- ASSERT(!ec); | |
- | |
- if (elem->renderer() && elem->renderer()->canHaveChildren()) { | |
- elem->appendChild(styleElement, ec); | |
- } else { | |
- Node *parent = elem->parent(); | |
- Node *next = elem->nextSibling(); | |
- | |
- if (next) | |
- parent->insertBefore(styleElement, next, ec); | |
- else | |
- parent->appendChild(styleElement, ec); | |
- } | |
- ASSERT(!ec); | |
- | |
- nodeToRemove = styleElement.get(); | |
- } | |
- | |
- return computedStyle(styleElement.release()); | |
-} | |
- | |
-void Frame::textFieldDidBeginEditing(Element* e) | |
-{ | |
- if (editor()->client()) | |
- editor()->client()->textFieldDidBeginEditing(e); | |
-} | |
- | |
-void Frame::textFieldDidEndEditing(Element* e) | |
-{ | |
- if (editor()->client()) | |
- editor()->client()->textFieldDidEndEditing(e); | |
-} | |
- | |
-void Frame::textDidChangeInTextField(Element* e) | |
-{ | |
- if (editor()->client()) | |
- editor()->client()->textDidChangeInTextField(e); | |
-} | |
- | |
-bool Frame::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke) | |
-{ | |
- if (editor()->client()) | |
- return editor()->client()->doTextFieldCommandFromEvent(e, ke); | |
- | |
- return false; | |
-} | |
- | |
-void Frame::textWillBeDeletedInTextField(Element* input) | |
-{ | |
- if (editor()->client()) | |
- editor()->client()->textWillBeDeletedInTextField(input); | |
-} | |
- | |
-void Frame::textDidChangeInTextArea(Element* e) | |
-{ | |
- if (editor()->client()) | |
- editor()->client()->textDidChangeInTextArea(e); | |
-} | |
- | |
-void Frame::applyEditingStyleToBodyElement() const | |
-{ | |
- RefPtr<NodeList> list = m_doc->getElementsByTagName("body"); | |
- unsigned len = list->length(); | |
- for (unsigned i = 0; i < len; i++) | |
- applyEditingStyleToElement(static_cast<Element*>(list->item(i))); | |
-} | |
- | |
-void Frame::removeEditingStyleFromBodyElement() const | |
-{ | |
- RefPtr<NodeList> list = m_doc->getElementsByTagName("body"); | |
- unsigned len = list->length(); | |
- for (unsigned i = 0; i < len; i++) | |
- removeEditingStyleFromElement(static_cast<Element*>(list->item(i))); | |
-} | |
- | |
-void Frame::applyEditingStyleToElement(Element* element) const | |
-{ | |
- if (!element) | |
- return; | |
- | |
- CSSStyleDeclaration* style = element->style(); | |
- ASSERT(style); | |
- | |
- ExceptionCode ec = 0; | |
- style->setProperty(CSSPropertyWordWrap, "break-word", false, ec); | |
- ASSERT(!ec); | |
- style->setProperty(CSSPropertyWebkitNbspMode, "space", false, ec); | |
- ASSERT(!ec); | |
- style->setProperty(CSSPropertyWebkitLineBreak, "after-white-space", false, ec); | |
- ASSERT(!ec); | |
-} | |
- | |
-void Frame::removeEditingStyleFromElement(Element*) const | |
-{ | |
-} | |
- | |
-#ifndef NDEBUG | |
-#if PLATFORM(WKC) | |
-static HashSet<Frame*>* gStaticKeepAliveSet = 0; | |
-static HashSet<Frame*>& keepAliveSet() | |
-{ | |
- if (!gStaticKeepAliveSet) { | |
- gStaticKeepAliveSet = new HashSet<Frame*>(); | |
- } | |
- HashSet<Frame*>& staticKeepAliveSet = *gStaticKeepAliveSet; | |
- return staticKeepAliveSet; | |
-} | |
-#else | |
-static HashSet<Frame*>& keepAliveSet() | |
-{ | |
- DEFINE_STATIC_LOCAL(HashSet<Frame*>, staticKeepAliveSet, ()); | |
- return staticKeepAliveSet; | |
-} | |
-#endif | |
-#endif | |
- | |
-void Frame::keepAlive() | |
-{ | |
- if (m_lifeSupportTimer.isActive()) | |
- return; | |
-#ifndef NDEBUG | |
- keepAliveSet().add(this); | |
-#endif | |
- ref(); | |
- m_lifeSupportTimer.startOneShot(0); | |
-} | |
- | |
-#ifndef NDEBUG | |
-void Frame::cancelAllKeepAlive() | |
-{ | |
- HashSet<Frame*>::iterator end = keepAliveSet().end(); | |
- for (HashSet<Frame*>::iterator it = keepAliveSet().begin(); it != end; ++it) { | |
- Frame* frame = *it; | |
- frame->m_lifeSupportTimer.stop(); | |
- frame->deref(); | |
- } | |
- keepAliveSet().clear(); | |
-} | |
-#endif | |
- | |
-void Frame::lifeSupportTimerFired(Timer<Frame>*) | |
-{ | |
-#ifndef NDEBUG | |
- keepAliveSet().remove(this); | |
-#endif | |
- deref(); | |
-} | |
- | |
-void Frame::clearDOMWindow() | |
-{ | |
- if (m_domWindow) { | |
- m_liveFormerWindows.add(m_domWindow.get()); | |
- m_domWindow->clear(); | |
- } | |
- m_domWindow = 0; | |
-} | |
- | |
-RenderView* Frame::contentRenderer() const | |
-{ | |
- Document* doc = document(); | |
- if (!doc) | |
- return 0; | |
- RenderObject* object = doc->renderer(); | |
- if (!object) | |
- return 0; | |
- ASSERT(object->isRenderView()); | |
- return toRenderView(object); | |
-} | |
- | |
-HTMLFrameOwnerElement* Frame::ownerElement() const | |
-{ | |
- return m_ownerElement; | |
-} | |
- | |
-RenderPart* Frame::ownerRenderer() const | |
-{ | |
- HTMLFrameOwnerElement* ownerElement = m_ownerElement; | |
- if (!ownerElement) | |
- return 0; | |
- RenderObject* object = ownerElement->renderer(); | |
- if (!object) | |
- return 0; | |
- // FIXME: If <object> is ever fixed to disassociate itself from frames | |
- // that it has started but canceled, then this can turn into an ASSERT | |
- // since m_ownerElement would be 0 when the load is canceled. | |
- // https://bugs.webkit.org/show_bug.cgi?id=18585 | |
- if (!object->isRenderPart()) | |
- return 0; | |
- return toRenderPart(object); | |
-} | |
- | |
-bool Frame::isDisconnected() const | |
-{ | |
- return m_isDisconnected; | |
-} | |
- | |
-void Frame::setIsDisconnected(bool isDisconnected) | |
-{ | |
- m_isDisconnected = isDisconnected; | |
-} | |
- | |
-bool Frame::excludeFromTextSearch() const | |
-{ | |
- return m_excludeFromTextSearch; | |
-} | |
- | |
-void Frame::setExcludeFromTextSearch(bool exclude) | |
-{ | |
- m_excludeFromTextSearch = exclude; | |
-} | |
- | |
-// returns FloatRect because going through IntRect would truncate any floats | |
-FloatRect Frame::selectionBounds(bool clipToVisibleContent) const | |
-{ | |
- RenderView* root = contentRenderer(); | |
- FrameView* view = m_view.get(); | |
- if (!root || !view) | |
- return IntRect(); | |
- | |
- IntRect selectionRect = root->selectionBounds(clipToVisibleContent); | |
- return clipToVisibleContent ? intersection(selectionRect, view->visibleContentRect()) : selectionRect; | |
-} | |
- | |
-void Frame::selectionTextRects(Vector<FloatRect>& rects, SelectionRectRespectTransforms respectTransforms, bool clipToVisibleContent) const | |
-{ | |
- RenderView* root = contentRenderer(); | |
- if (!root) | |
- return; | |
- | |
- RefPtr<Range> selectedRange = selection()->toNormalizedRange(); | |
- | |
- FloatRect visibleContentRect = m_view->visibleContentRect(); | |
- | |
- // FIMXE: we are appending empty rects to the list for those that fall outside visibleContentRect. | |
- // We may not want to do that. | |
- if (respectTransforms) { | |
- Vector<FloatQuad> quads; | |
- selectedRange->textQuads(quads, true); | |
- | |
- unsigned size = quads.size(); | |
- for (unsigned i = 0; i < size; ++i) { | |
- IntRect currRect = quads[i].enclosingBoundingBox(); | |
- if (clipToVisibleContent) | |
- rects.append(intersection(currRect, visibleContentRect)); | |
- else | |
- rects.append(currRect); | |
- } | |
- } else { | |
- Vector<IntRect> intRects; | |
- selectedRange->textRects(intRects, true); | |
- | |
- unsigned size = intRects.size(); | |
- for (unsigned i = 0; i < size; ++i) { | |
- if (clipToVisibleContent) | |
- rects.append(intersection(intRects[i], visibleContentRect)); | |
- else | |
- rects.append(intRects[i]); | |
- } | |
- } | |
-} | |
- | |
-// Scans logically forward from "start", including any child frames | |
-static HTMLFormElement *scanForForm(Node *start) | |
-{ | |
- Node *n; | |
- for (n = start; n; n = n->traverseNextNode()) { | |
- if (n->hasTagName(formTag)) | |
- return static_cast<HTMLFormElement*>(n); | |
- else if (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement()) | |
- return static_cast<HTMLFormControlElement*>(n)->form(); | |
- else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) { | |
- Node *childDoc = static_cast<HTMLFrameElementBase*>(n)->contentDocument(); | |
- if (HTMLFormElement *frameResult = scanForForm(childDoc)) | |
- return frameResult; | |
- } | |
- } | |
- return 0; | |
-} | |
- | |
-// We look for either the form containing the current focus, or for one immediately after it | |
-HTMLFormElement *Frame::currentForm() const | |
-{ | |
- // start looking either at the active (first responder) node, or where the selection is | |
- Node *start = m_doc ? m_doc->focusedNode() : 0; | |
- if (!start) | |
- start = selection()->start().node(); | |
- | |
- // try walking up the node tree to find a form element | |
- Node *n; | |
- for (n = start; n; n = n->parentNode()) { | |
- if (n->hasTagName(formTag)) | |
- return static_cast<HTMLFormElement*>(n); | |
- else if (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement()) | |
- return static_cast<HTMLFormControlElement*>(n)->form(); | |
- } | |
- | |
- // try walking forward in the node tree to find a form element | |
- return start ? scanForForm(start) : 0; | |
-} | |
- | |
-void Frame::revealSelection(const ScrollAlignment& alignment, bool revealExtent) | |
-{ | |
- IntRect rect; | |
- | |
- switch (selection()->selectionType()) { | |
- case VisibleSelection::NoSelection: | |
- return; | |
- case VisibleSelection::CaretSelection: | |
- rect = selection()->absoluteCaretBounds(); | |
- break; | |
- case VisibleSelection::RangeSelection: | |
- rect = revealExtent ? VisiblePosition(selection()->extent()).absoluteCaretBounds() : enclosingIntRect(selectionBounds(false)); | |
- break; | |
- } | |
- | |
- Position start = selection()->start(); | |
- ASSERT(start.node()); | |
- if (start.node() && start.node()->renderer()) { | |
- // FIXME: This code only handles scrolling the startContainer's layer, but | |
- // the selection rect could intersect more than just that. | |
- // See <rdar://problem/4799899>. | |
- if (RenderLayer* layer = start.node()->renderer()->enclosingLayer()) | |
- layer->scrollRectToVisible(rect, false, alignment, alignment); | |
- } | |
-} | |
- | |
-Frame* Frame::frameForWidget(const Widget* widget) | |
-{ | |
- ASSERT_ARG(widget, widget); | |
- | |
- if (RenderWidget* renderer = RenderWidget::find(widget)) | |
- if (Node* node = renderer->node()) | |
- return node->document()->frame(); | |
- | |
- // Assume all widgets are either a FrameView or owned by a RenderWidget. | |
- // FIXME: That assumption is not right for scroll bars! | |
- ASSERT(widget->isFrameView()); | |
- return static_cast<const FrameView*>(widget)->frame(); | |
-} | |
- | |
-void Frame::clearTimers(FrameView *view, Document *document) | |
-{ | |
- if (view) { | |
- view->unscheduleRelayout(); | |
- if (view->frame()) { | |
- view->frame()->animation()->suspendAnimations(document); | |
- view->frame()->eventHandler()->stopAutoscrollTimer(); | |
- } | |
- } | |
-} | |
- | |
-void Frame::clearTimers() | |
-{ | |
- clearTimers(m_view.get(), document()); | |
-} | |
- | |
-RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const | |
-{ | |
- nodeToRemove = 0; | |
- | |
- if (selection()->isNone()) | |
- return 0; | |
- | |
- Position pos = selection()->selection().visibleStart().deepEquivalent(); | |
- if (!pos.isCandidate()) | |
- return 0; | |
- Node *node = pos.node(); | |
- if (!node) | |
- return 0; | |
- | |
- if (!m_typingStyle) | |
- return node->renderer()->style(); | |
- | |
- RefPtr<Element> styleElement = document()->createElement(spanTag, false); | |
- | |
- ExceptionCode ec = 0; | |
- String styleText = m_typingStyle->cssText() + " display: inline"; | |
- styleElement->setAttribute(styleAttr, styleText.impl(), ec); | |
- ASSERT(!ec); | |
- | |
- styleElement->appendChild(document()->createEditingTextNode(""), ec); | |
- ASSERT(!ec); | |
- | |
- node->parentNode()->appendChild(styleElement, ec); | |
- ASSERT(!ec); | |
- | |
- nodeToRemove = styleElement.get(); | |
- return styleElement->renderer() ? styleElement->renderer()->style() : 0; | |
-} | |
- | |
-void Frame::setSelectionFromNone() | |
-{ | |
- // Put a caret inside the body if the entire frame is editable (either the | |
- // entire WebView is editable or designMode is on for this document). | |
- Document *doc = document(); | |
- bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); | |
- if (!selection()->isNone() || !(isContentEditable() || caretBrowsing)) | |
- return; | |
- | |
- Node* node = doc->documentElement(); | |
- while (node && !node->hasTagName(bodyTag)) | |
- node = node->traverseNextNode(); | |
- if (node) | |
- selection()->setSelection(VisibleSelection(Position(node, 0), DOWNSTREAM)); | |
-} | |
- | |
-bool Frame::inViewSourceMode() const | |
-{ | |
- return m_inViewSourceMode; | |
-} | |
- | |
-void Frame::setInViewSourceMode(bool mode) | |
-{ | |
- m_inViewSourceMode = mode; | |
-} | |
- | |
-// Searches from the beginning of the document if nothing is selected. | |
-bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection) | |
-{ | |
- if (target.isEmpty()) | |
- return false; | |
- | |
- if (excludeFromTextSearch()) | |
- return false; | |
- | |
- // Start from an edge of the selection, if there's a selection that's not in shadow content. Which edge | |
- // is used depends on whether we're searching forward or backward, and whether startInSelection is set. | |
- RefPtr<Range> searchRange(rangeOfContents(document())); | |
- VisibleSelection selection = this->selection()->selection(); | |
- | |
- if (forward) | |
- setStart(searchRange.get(), startInSelection ? selection.visibleStart() : selection.visibleEnd()); | |
- else | |
- setEnd(searchRange.get(), startInSelection ? selection.visibleEnd() : selection.visibleStart()); | |
- | |
- Node* shadowTreeRoot = selection.shadowTreeRootNode(); | |
- if (shadowTreeRoot) { | |
- ExceptionCode ec = 0; | |
- if (forward) | |
- searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec); | |
- else | |
- searchRange->setStart(shadowTreeRoot, 0, ec); | |
- } | |
- | |
- RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, forward, caseFlag)); | |
- // If we started in the selection and the found range exactly matches the existing selection, find again. | |
- // Build a selection with the found range to remove collapsed whitespace. | |
- // Compare ranges instead of selection objects to ignore the way that the current selection was made. | |
- if (startInSelection && *VisibleSelection(resultRange.get()).toNormalizedRange() == *selection.toNormalizedRange()) { | |
- searchRange = rangeOfContents(document()); | |
- if (forward) | |
- setStart(searchRange.get(), selection.visibleEnd()); | |
- else | |
- setEnd(searchRange.get(), selection.visibleStart()); | |
- | |
- if (shadowTreeRoot) { | |
- ExceptionCode ec = 0; | |
- if (forward) | |
- searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec); | |
- else | |
- searchRange->setStart(shadowTreeRoot, 0, ec); | |
- } | |
- | |
- resultRange = findPlainText(searchRange.get(), target, forward, caseFlag); | |
- } | |
- | |
- ExceptionCode exception = 0; | |
- | |
- // If nothing was found in the shadow tree, search in main content following the shadow tree. | |
- if (resultRange->collapsed(exception) && shadowTreeRoot) { | |
- searchRange = rangeOfContents(document()); | |
- if (forward) | |
- searchRange->setStartAfter(shadowTreeRoot->shadowParentNode(), exception); | |
- else | |
- searchRange->setEndBefore(shadowTreeRoot->shadowParentNode(), exception); | |
- | |
- resultRange = findPlainText(searchRange.get(), target, forward, caseFlag); | |
- } | |
- | |
- if (!editor()->insideVisibleArea(resultRange.get())) { | |
- resultRange = editor()->nextVisibleRange(resultRange.get(), target, forward, caseFlag, wrapFlag); | |
- if (!resultRange) | |
- return false; | |
- } | |
- | |
- // If we didn't find anything and we're wrapping, search again in the entire document (this will | |
- // redundantly re-search the area already searched in some cases). | |
- if (resultRange->collapsed(exception) && wrapFlag) { | |
- searchRange = rangeOfContents(document()); | |
- resultRange = findPlainText(searchRange.get(), target, forward, caseFlag); | |
- // We used to return false here if we ended up with the same range that we started with | |
- // (e.g., the selection was already the only instance of this text). But we decided that | |
- // this should be a success case instead, so we'll just fall through in that case. | |
- } | |
- | |
- if (resultRange->collapsed(exception)) | |
- return false; | |
- | |
- this->selection()->setSelection(VisibleSelection(resultRange.get(), DOWNSTREAM)); | |
- revealSelection(); | |
- return true; | |
-} | |
- | |
-unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsigned limit) | |
-{ | |
- if (target.isEmpty()) | |
- return 0; | |
- | |
- RefPtr<Range> searchRange(rangeOfContents(document())); | |
- | |
- ExceptionCode exception = 0; | |
- unsigned matchCount = 0; | |
- do { | |
- RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag)); | |
- if (resultRange->collapsed(exception)) { | |
- if (!resultRange->startContainer()->isInShadowTree()) | |
- break; | |
- | |
- searchRange = rangeOfContents(document()); | |
- searchRange->setStartAfter(resultRange->startContainer()->shadowAncestorNode(), exception); | |
- continue; | |
- } | |
- | |
- // A non-collapsed result range can in some funky whitespace cases still not | |
- // advance the range's start position (4509328). Break to avoid infinite loop. | |
- VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM); | |
- if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM)) | |
- break; | |
- | |
- // Only treat the result as a match if it is visible | |
- if (editor()->insideVisibleArea(resultRange.get())) { | |
- ++matchCount; | |
- document()->addMarker(resultRange.get(), DocumentMarker::TextMatch); | |
- } | |
- | |
- // Stop looking if we hit the specified limit. A limit of 0 means no limit. | |
- if (limit > 0 && matchCount >= limit) | |
- break; | |
- | |
- setStart(searchRange.get(), newStart); | |
- Node* shadowTreeRoot = searchRange->shadowTreeRootNode(); | |
- if (searchRange->collapsed(exception) && shadowTreeRoot) | |
- searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), exception); | |
- } while (true); | |
- | |
- // Do a "fake" paint in order to execute the code that computes the rendered rect for | |
- // each text match. | |
- Document* doc = document(); | |
- if (m_view && contentRenderer()) { | |
- doc->updateLayout(); // Ensure layout is up to date. | |
- IntRect visibleRect = m_view->visibleContentRect(); | |
- if (!visibleRect.isEmpty()) { | |
- GraphicsContext context((PlatformGraphicsContext*)0); | |
- context.setPaintingDisabled(true); | |
- m_view->paintContents(&context, visibleRect); | |
- } | |
- } | |
- | |
- return matchCount; | |
-} | |
- | |
-bool Frame::markedTextMatchesAreHighlighted() const | |
-{ | |
- return m_highlightTextMatches; | |
-} | |
- | |
-void Frame::setMarkedTextMatchesAreHighlighted(bool flag) | |
-{ | |
- if (flag == m_highlightTextMatches) | |
- return; | |
- | |
- m_highlightTextMatches = flag; | |
- document()->repaintMarkers(DocumentMarker::TextMatch); | |
-} | |
- | |
-FrameTree* Frame::tree() const | |
-{ | |
- return &m_treeNode; | |
-} | |
- | |
-void Frame::setDOMWindow(DOMWindow* domWindow) | |
-{ | |
- if (m_domWindow) { | |
- m_liveFormerWindows.add(m_domWindow.get()); | |
- m_domWindow->clear(); | |
- } | |
- m_domWindow = domWindow; | |
-} | |
- | |
-DOMWindow* Frame::domWindow() const | |
-{ | |
- if (!m_domWindow) | |
- m_domWindow = DOMWindow::create(const_cast<Frame*>(this)); | |
- | |
- return m_domWindow.get(); | |
-} | |
- | |
-void Frame::clearFormerDOMWindow(DOMWindow* window) | |
-{ | |
- m_liveFormerWindows.remove(window); | |
-} | |
- | |
-Page* Frame::page() const | |
-{ | |
- return m_page; | |
-} | |
- | |
-void Frame::detachFromPage() | |
-{ | |
- m_page = 0; | |
-} | |
- | |
-EventHandler* Frame::eventHandler() const | |
-{ | |
- return &m_eventHandler; | |
-} | |
- | |
-void Frame::pageDestroyed() | |
-{ | |
- if (Frame* parent = tree()->parent()) | |
- parent->loader()->checkLoadComplete(); | |
- | |
- // FIXME: It's unclear as to why this is called more than once, but it is, | |
- // so page() could be NULL. | |
- if (page() && page()->focusController()->focusedFrame() == this) | |
- page()->focusController()->setFocusedFrame(0); | |
- | |
- script()->clearWindowShell(); | |
- script()->clearScriptObjects(); | |
- script()->updatePlatformScriptObjects(); | |
- | |
- detachFromPage(); | |
-} | |
- | |
-void Frame::disconnectOwnerElement() | |
-{ | |
- if (m_ownerElement) { | |
- if (Document* doc = document()) | |
- doc->clearAXObjectCache(); | |
- m_ownerElement->m_contentFrame = 0; | |
- if (m_page) | |
- m_page->decrementFrameCount(); | |
- } | |
- m_ownerElement = 0; | |
-} | |
- | |
-String Frame::documentTypeString() const | |
-{ | |
- if (DocumentType* doctype = document()->doctype()) | |
- return createMarkup(doctype); | |
- | |
- return String(); | |
-} | |
- | |
-void Frame::focusWindow() | |
-{ | |
- if (!page()) | |
- return; | |
- | |
- // If we're a top level window, bring the window to the front. | |
- if (!tree()->parent()) | |
- page()->chrome()->focus(); | |
- | |
- eventHandler()->focusDocumentView(); | |
-} | |
- | |
-void Frame::unfocusWindow() | |
-{ | |
- if (!page()) | |
- return; | |
- | |
- // If we're a top level window, deactivate the window. | |
- if (!tree()->parent()) | |
- page()->chrome()->unfocus(); | |
-} | |
- | |
-bool Frame::shouldClose() | |
-{ | |
- Chrome* chrome = page() ? page()->chrome() : 0; | |
- if (!chrome || !chrome->canRunBeforeUnloadConfirmPanel()) | |
- return true; | |
- | |
- if (!m_domWindow) | |
- return true; | |
- | |
- RefPtr<Document> doc = document(); | |
- HTMLElement* body = doc->body(); | |
- if (!body) | |
- return true; | |
- | |
- RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create(); | |
- m_domWindow->dispatchEvent(beforeUnloadEvent.get(), m_domWindow->document()); | |
- | |
- if (!beforeUnloadEvent->defaultPrevented()) | |
- doc->defaultEventHandler(beforeUnloadEvent.get()); | |
- if (beforeUnloadEvent->result().isNull()) | |
- return true; | |
- | |
- String text = doc->displayStringModifiedByEncoding(beforeUnloadEvent->result()); | |
- return chrome->runBeforeUnloadConfirmPanel(text, this); | |
-} | |
- | |
-void Frame::scheduleClose() | |
-{ | |
- if (!shouldClose()) | |
- return; | |
- | |
- Chrome* chrome = page() ? page()->chrome() : 0; | |
- if (chrome) | |
- chrome->closeWindowSoon(); | |
-} | |
- | |
-void Frame::respondToChangedSelection(const VisibleSelection& oldSelection, bool closeTyping) | |
-{ | |
- bool isContinuousSpellCheckingEnabled = editor()->isContinuousSpellCheckingEnabled(); | |
- bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && editor()->isGrammarCheckingEnabled(); | |
- if (isContinuousSpellCheckingEnabled) { | |
- VisibleSelection newAdjacentWords; | |
- VisibleSelection newSelectedSentence; | |
- bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); | |
- if (selection()->selection().isContentEditable() || caretBrowsing) { | |
- VisiblePosition newStart(selection()->selection().visibleStart()); | |
- newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary)); | |
- if (isContinuousGrammarCheckingEnabled) | |
- newSelectedSentence = VisibleSelection(startOfSentence(newStart), endOfSentence(newStart)); | |
- } | |
- | |
- // When typing we check spelling elsewhere, so don't redo it here. | |
- // If this is a change in selection resulting from a delete operation, | |
- // oldSelection may no longer be in the document. | |
- if (closeTyping && oldSelection.isContentEditable() && oldSelection.start().node() && oldSelection.start().node()->inDocument()) { | |
- VisiblePosition oldStart(oldSelection.visibleStart()); | |
- VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary)); | |
- if (oldAdjacentWords != newAdjacentWords) { | |
- if (isContinuousGrammarCheckingEnabled) { | |
- VisibleSelection oldSelectedSentence = VisibleSelection(startOfSentence(oldStart), endOfSentence(oldStart)); | |
- editor()->markMisspellingsAndBadGrammar(oldAdjacentWords, oldSelectedSentence != newSelectedSentence, oldSelectedSentence); | |
- } else | |
- editor()->markMisspellingsAndBadGrammar(oldAdjacentWords, false, oldAdjacentWords); | |
- } | |
- } | |
- | |
- // This only erases markers that are in the first unit (word or sentence) of the selection. | |
- // Perhaps peculiar, but it matches AppKit. | |
- if (RefPtr<Range> wordRange = newAdjacentWords.toNormalizedRange()) | |
- document()->removeMarkers(wordRange.get(), DocumentMarker::Spelling); | |
- if (RefPtr<Range> sentenceRange = newSelectedSentence.toNormalizedRange()) | |
- document()->removeMarkers(sentenceRange.get(), DocumentMarker::Grammar); | |
- } | |
- | |
- // When continuous spell checking is off, existing markers disappear after the selection changes. | |
- if (!isContinuousSpellCheckingEnabled) | |
- document()->removeMarkers(DocumentMarker::Spelling); | |
- if (!isContinuousGrammarCheckingEnabled) | |
- document()->removeMarkers(DocumentMarker::Grammar); | |
- | |
- editor()->respondToChangedSelection(oldSelection); | |
-} | |
- | |
-VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint) | |
-{ | |
- HitTestResult result = eventHandler()->hitTestResultAtPoint(framePoint, true); | |
- Node* node = result.innerNode(); | |
- if (!node) | |
- return VisiblePosition(); | |
- RenderObject* renderer = node->renderer(); | |
- if (!renderer) | |
- return VisiblePosition(); | |
- VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint()); | |
- if (visiblePos.isNull()) | |
- visiblePos = VisiblePosition(Position(node, 0)); | |
- return visiblePos; | |
-} | |
- | |
-Document* Frame::documentAtPoint(const IntPoint& point) | |
-{ | |
- if (!view()) | |
- return 0; | |
- | |
- IntPoint pt = view()->windowToContents(point); | |
- HitTestResult result = HitTestResult(pt); | |
- | |
- if (contentRenderer()) | |
- result = eventHandler()->hitTestResultAtPoint(pt, false); | |
- return result.innerNode() ? result.innerNode()->document() : 0; | |
-} | |
- | |
-void Frame::createView(const IntSize& viewportSize, | |
- const Color& backgroundColor, bool transparent, | |
- const IntSize& fixedLayoutSize, bool useFixedLayout, | |
- ScrollbarMode horizontalScrollbarMode, ScrollbarMode verticalScrollbarMode) | |
-{ | |
- ASSERT(this); | |
- ASSERT(m_page); | |
- | |
- bool isMainFrame = this == m_page->mainFrame(); | |
- | |
- if (isMainFrame && view()) | |
- view()->setParentVisible(false); | |
- | |
- setView(0); | |
- | |
- RefPtr<FrameView> frameView; | |
- if (isMainFrame) { | |
- frameView = FrameView::create(this, viewportSize); | |
- frameView->setFixedLayoutSize(fixedLayoutSize); | |
- frameView->setUseFixedLayout(useFixedLayout); | |
- } else | |
- frameView = FrameView::create(this); | |
- | |
- frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode); | |
- | |
- setView(frameView); | |
- | |
- if (backgroundColor.isValid()) | |
- frameView->updateBackgroundRecursively(backgroundColor, transparent); | |
- | |
- if (isMainFrame) | |
- frameView->setParentVisible(true); | |
- | |
- if (ownerRenderer()) | |
- ownerRenderer()->setWidget(frameView); | |
- | |
- if (HTMLFrameOwnerElement* owner = ownerElement()) | |
- view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff); | |
-} | |
- | |
-#if PLATFORM(WKC) | |
-void Frame::deleteSharedInstance() | |
-{ | |
- HTMLNames::finalize(); | |
-#if ENABLE(SVG) | |
- SVGNames::finalize(); | |
- XLinkNames::finalize(); | |
-#endif | |
- | |
-#if ENABLE(WML) | |
- WMLNames::finalize(); | |
-#endif | |
- | |
-#if ENABLE(MATHML) | |
- MathMLNames::finalize(); | |
-#endif | |
- XMLNames::finalize(); | |
- | |
- delete gWordRegExp; | |
-#ifndef NDEBUG | |
- delete gStaticKeepAliveSet; | |
- delete gFrameCounter; | |
-#endif | |
-} | |
- | |
-void Frame::resetVariables() | |
-{ | |
- HTMLNames::finalize(); | |
-#if ENABLE(SVG) | |
- SVGNames::finalize(); | |
- XLinkNames::finalize(); | |
-#endif | |
- | |
-#if ENABLE(WML) | |
- WMLNames::finalize(); | |
-#endif | |
- | |
-#if ENABLE(MATHML) | |
- MathMLNames::finalize(); | |
-#endif | |
- XMLNames::finalize(); | |
- | |
- gWordRegExp = 0; | |
-#ifndef NDEBUG | |
- gStaticKeepAliveSet = 0; | |
- gFrameCounter = 0; | |
-#endif | |
-} | |
-#endif | |
- | |
-#if ENABLE(WKC_FRAME_FLATTENING) | |
-void Frame::invalidateOwnerRendererLayoutIfNeeded() | |
-{ | |
- if (settings() && settings()->flatFrameSetLayoutEnabled() && ownerRenderer()) | |
- ownerRenderer()->setNeedsLayout(true, true); | |
-} | |
- | |
-bool Frame::isFrameSet() const | |
-{ | |
- Document* doc = m_doc.get(); | |
- if (!doc || !doc->isHTMLDocument()) | |
- return false; | |
- Node *body = static_cast<HTMLDocument*>(doc)->body(); | |
- return body && body->renderer() && body->hasTagName(framesetTag); | |
-} | |
- | |
-#endif | |
-} // namespace WebCore | |
+ document()->updateStyleIfNeeded(); | |
+#endif | |
+ | |
+ RenderView* view = contentRenderer(); | |
+ if (!view) | |
+ return; | |
+ | |
+ VisibleSelection selection = this->selection()->selection(); | |
+ | |
+ if (!selection.isRange()) | |
+ view->clearSelection(); | |
+ else { | |
+ // Use the rightmost candidate for the start of the selection, and the leftmost candidate for the end of the selection. | |
+ // Example: foo <a>bar</a>. Imagine that a line wrap occurs after 'foo', and that 'bar' is selected. If we pass [foo, 3] | |
+ // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected | |
+ // and will fill the gap before 'bar'. | |
+ Position startPos = selection.start(); | |
+ if (startPos.downstream().isCandidate()) | |
+ startPos = startPos.downstream(); | |
+ Position endPos = selection.end(); | |
+ if (endPos.upstream().isCandidate()) | |
+ endPos = endPos.upstream(); | |
+ | |
+ // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted | |
+ // because we don't yet notify the SelectionController of text removal. | |
+ if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) { | |
+ RenderObject *startRenderer = startPos.node()->renderer(); | |
+ RenderObject *endRenderer = endPos.node()->renderer(); | |
+ view->setSelection(startRenderer, startPos.deprecatedEditingOffset(), endRenderer, endPos.deprecatedEditingOffset()); | |
+ } | |
+ } | |
+} | |
+ | |
+void Frame::caretBlinkTimerFired(Timer<Frame>*) | |
+{ | |
+#if ENABLE(TEXT_CARET) | |
+ if (!m_caretVisible || !selection()->isCaret()) { | |
+ ASSERT(selection()->needsDisplayUpdate()); | |
+ return; | |
+ } | |
+ bool caretPaint = m_caretPaint; | |
+ if (selection()->isCaretBlinkingSuspended() && caretPaint) | |
+ return; | |
+ m_caretPaint = !caretPaint; | |
+ selection()->invalidateCaretRect(); | |
+#endif | |
+} | |
+ | |
+void Frame::paintCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect) const | |
+{ | |
+#if ENABLE(TEXT_CARET) | |
+ if (m_caretPaint && m_caretVisible) | |
+ selection()->paintCaret(p, tx, ty, clipRect); | |
+#endif | |
+} | |
+ | |
+void Frame::paintDragCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect) const | |
+{ | |
+#if ENABLE(TEXT_CARET) | |
+ SelectionController* dragCaretController = m_page->dragCaretController(); | |
+ ASSERT(dragCaretController->selection().isCaret()); | |
+ if (dragCaretController->selection().start().node()->document()->frame() == this) | |
+ dragCaretController->paintCaret(p, tx, ty, clipRect); | |
+#endif | |
+} | |
+ | |
+float Frame::zoomFactor() const | |
+{ | |
+ return m_zoomFactor; | |
+} | |
+ | |
+bool Frame::isZoomFactorTextOnly() const | |
+{ | |
+ return m_page->settings()->zoomsTextOnly(); | |
+} | |
+ | |
+bool Frame::shouldApplyTextZoom() const | |
+{ | |
+ if (m_zoomFactor == 1.0f || !isZoomFactorTextOnly()) | |
+ return false; | |
+#if ENABLE(SVG) | |
+ if (m_doc->isSVGDocument()) | |
+ return false; | |
+#endif | |
+ return true; | |
+} | |
+ | |
+bool Frame::shouldApplyPageZoom() const | |
+{ | |
+ if (m_zoomFactor == 1.0f || isZoomFactorTextOnly()) | |
+ return false; | |
+#if ENABLE(SVG) | |
+ if (m_doc->isSVGDocument()) | |
+ return false; | |
+#endif | |
+ return true; | |
+} | |
+ | |
+void Frame::setZoomFactor(float percent, bool isTextOnly) | |
+{ | |
+ if (m_zoomFactor == percent && isZoomFactorTextOnly() == isTextOnly) | |
+ return; | |
+ | |
+#if ENABLE(SVG) | |
+ // SVG doesn't care if the zoom factor is text only. It will always apply a | |
+ // zoom to the whole SVG. | |
+ if (m_doc->isSVGDocument()) { | |
+ if (!static_cast<SVGDocument*>(m_doc.get())->zoomAndPanEnabled()) | |
+ return; | |
+ m_zoomFactor = percent; | |
+ m_page->settings()->setZoomsTextOnly(true); // We do this to avoid doing any scaling of CSS pixels, since the SVG has its own notion of zoom. | |
+ if (m_doc->renderer()) | |
+ m_doc->renderer()->repaint(); | |
+ return; | |
+ } | |
+#endif | |
+ | |
+ m_zoomFactor = percent; | |
+ m_page->settings()->setZoomsTextOnly(isTextOnly); | |
+ | |
+ m_doc->recalcStyle(Node::Force); | |
+ | |
+ for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling()) | |
+ child->setZoomFactor(m_zoomFactor, isTextOnly); | |
+ | |
+ if (m_doc->renderer() && m_doc->renderer()->needsLayout() && view()->didFirstLayout()) | |
+ view()->layout(); | |
+} | |
+ | |
+void Frame::setPrinting(bool printing, float minPageWidth, float maxPageWidth, bool adjustViewSize) | |
+{ | |
+ m_doc->setPrinting(printing); | |
+ view()->setMediaType(printing ? "print" : "screen"); | |
+ m_doc->updateStyleSelector(); | |
+ view()->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, adjustViewSize); | |
+ | |
+ for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling()) | |
+ child->setPrinting(printing, minPageWidth, maxPageWidth, adjustViewSize); | |
+} | |
+ | |
+void Frame::setJSStatusBarText(const String& text) | |
+{ | |
+ ASSERT(m_doc); // Client calls shouldn't be made when the frame is in inconsistent state. | |
+ m_kjsStatusBarText = text; | |
+ if (m_page) | |
+ m_page->chrome()->setStatusbarText(this, m_kjsStatusBarText); | |
+} | |
+ | |
+void Frame::setJSDefaultStatusBarText(const String& text) | |
+{ | |
+ ASSERT(m_doc); // Client calls shouldn't be made when the frame is in inconsistent state. | |
+ m_kjsDefaultStatusBarText = text; | |
+ if (m_page) | |
+ m_page->chrome()->setStatusbarText(this, m_kjsDefaultStatusBarText); | |
+} | |
+ | |
+String Frame::jsStatusBarText() const | |
+{ | |
+ return m_kjsStatusBarText; | |
+} | |
+ | |
+String Frame::jsDefaultStatusBarText() const | |
+{ | |
+ return m_kjsDefaultStatusBarText; | |
+} | |
+ | |
+void Frame::setNeedsReapplyStyles() | |
+{ | |
+ // When the frame is not showing web content, it doesn't make sense to apply styles. | |
+ // If we tried, we'd end up doing things with the document, but the document, if one | |
+ // exists, is not currently shown and should be in the page cache. | |
+ if (!m_loader.client()->hasHTMLView()) | |
+ return; | |
+ | |
+ if (m_needsReapplyStyles) | |
+ return; | |
+ | |
+ m_needsReapplyStyles = true; | |
+ | |
+ // FrameView's "layout" timer includes reapplyStyles, so despite its | |
+ // name, it's what we want to call here. | |
+ if (view()) | |
+ view()->scheduleRelayout(); | |
+} | |
+ | |
+bool Frame::needsReapplyStyles() const | |
+{ | |
+ return m_needsReapplyStyles; | |
+} | |
+ | |
+void Frame::reapplyStyles() | |
+{ | |
+ m_needsReapplyStyles = false; | |
+ | |
+ // FIXME: This call doesn't really make sense in a function called reapplyStyles. | |
+ // We should probably eventually move it into its own function. | |
+ m_doc->docLoader()->setAutoLoadImages(m_page && m_page->settings()->loadsImagesAutomatically()); | |
+ | |
+ // FIXME: It's not entirely clear why the following is needed. | |
+ // The document automatically does this as required when you set the style sheet. | |
+ // But we had problems when this code was removed. Details are in | |
+ // <http://bugs.webkit.org/show_bug.cgi?id=8079>. | |
+ m_doc->updateStyleSelector(); | |
+} | |
+ | |
+void Frame::injectUserScripts(UserScriptInjectionTime injectionTime) | |
+{ | |
+ if (!m_page) | |
+ return; | |
+ | |
+ // Walk the hashtable. Inject by world. | |
+ const UserScriptMap* userScripts = m_page->group().userScripts(); | |
+ if (!userScripts) | |
+ return; | |
+ UserScriptMap::const_iterator end = userScripts->end(); | |
+ for (UserScriptMap::const_iterator it = userScripts->begin(); it != end; ++it) | |
+ injectUserScriptsForWorld(it->first.get(), *it->second, injectionTime); | |
+} | |
+ | |
+void Frame::injectUserScriptsForWorld(DOMWrapperWorld* world, const UserScriptVector& userScripts, UserScriptInjectionTime injectionTime) | |
+{ | |
+ if (userScripts.isEmpty()) | |
+ return; | |
+ | |
+ Document* doc = document(); | |
+ if (!doc) | |
+ return; | |
+ | |
+ Vector<ScriptSourceCode> sourceCode; | |
+ unsigned count = userScripts.size(); | |
+ for (unsigned i = 0; i < count; ++i) { | |
+ UserScript* script = userScripts[i].get(); | |
+ if (script->injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(doc->url(), script->whitelist(), script->blacklist())) | |
+ m_script.evaluateInWorld(ScriptSourceCode(script->source(), script->url()), world); | |
+ } | |
+} | |
+ | |
+bool Frame::shouldChangeSelection(const VisibleSelection& newSelection) const | |
+{ | |
+ return shouldChangeSelection(selection()->selection(), newSelection, newSelection.affinity(), false); | |
+} | |
+ | |
+bool Frame::shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity affinity, bool stillSelecting) const | |
+{ | |
+ return editor()->client()->shouldChangeSelectedRange(oldSelection.toNormalizedRange().get(), newSelection.toNormalizedRange().get(), | |
+ affinity, stillSelecting); | |
+} | |
+ | |
+bool Frame::shouldDeleteSelection(const VisibleSelection& selection) const | |
+{ | |
+ return editor()->client()->shouldDeleteRange(selection.toNormalizedRange().get()); | |
+} | |
+ | |
+bool Frame::isContentEditable() const | |
+{ | |
+ if (m_editor.clientIsEditable()) | |
+ return true; | |
+ return m_doc->inDesignMode(); | |
+} | |
+ | |
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) | |
+const short enableRomanKeyboardsOnly = -23; | |
+#endif | |
+void Frame::setUseSecureKeyboardEntry(bool enable) | |
+{ | |
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) | |
+ if (enable == IsSecureEventInputEnabled()) | |
+ return; | |
+ if (enable) { | |
+ EnableSecureEventInput(); | |
+#ifdef BUILDING_ON_TIGER | |
+ KeyScript(enableRomanKeyboardsOnly); | |
+#else | |
+ // WebKit substitutes nil for input context when in password field, which corresponds to null TSMDocument. So, there is | |
+ // no need to call TSMGetActiveDocument(), which may return an incorrect result when selection hasn't been yet updated | |
+ // after focusing a node. | |
+ CFArrayRef inputSources = TISCreateASCIICapableInputSourceList(); | |
+ TSMSetDocumentProperty(0, kTSMDocumentEnabledInputSourcesPropertyTag, sizeof(CFArrayRef), &inputSources); | |
+ CFRelease(inputSources); | |
+#endif | |
+ } else { | |
+ DisableSecureEventInput(); | |
+#ifdef BUILDING_ON_TIGER | |
+ KeyScript(smKeyEnableKybds); | |
+#else | |
+ TSMRemoveDocumentProperty(0, kTSMDocumentEnabledInputSourcesPropertyTag); | |
+#endif | |
+ } | |
+#endif | |
+} | |
+ | |
+void Frame::updateSecureKeyboardEntryIfActive() | |
+{ | |
+ if (selection()->isFocusedAndActive()) | |
+ setUseSecureKeyboardEntry(m_doc->useSecureKeyboardEntryWhenActive()); | |
+} | |
+ | |
+CSSMutableStyleDeclaration *Frame::typingStyle() const | |
+{ | |
+ return m_typingStyle.get(); | |
+} | |
+ | |
+void Frame::setTypingStyle(CSSMutableStyleDeclaration *style) | |
+{ | |
+ m_typingStyle = style; | |
+} | |
+ | |
+void Frame::clearTypingStyle() | |
+{ | |
+ m_typingStyle = 0; | |
+} | |
+ | |
+void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction) | |
+{ | |
+ if (!style || !style->length()) { | |
+ clearTypingStyle(); | |
+ return; | |
+ } | |
+ | |
+ // Calculate the current typing style. | |
+ RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable(); | |
+ if (typingStyle()) { | |
+ typingStyle()->merge(mutableStyle.get()); | |
+ mutableStyle = typingStyle(); | |
+ } | |
+ | |
+ RefPtr<CSSValue> unicodeBidi; | |
+ RefPtr<CSSValue> direction; | |
+ if (editingAction == EditActionSetWritingDirection) { | |
+ unicodeBidi = mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi); | |
+ direction = mutableStyle->getPropertyCSSValue(CSSPropertyDirection); | |
+ } | |
+ | |
+ Node* node = selection()->selection().visibleStart().deepEquivalent().node(); | |
+ computedStyle(node)->diff(mutableStyle.get()); | |
+ | |
+ if (editingAction == EditActionSetWritingDirection && unicodeBidi) { | |
+ ASSERT(unicodeBidi->isPrimitiveValue()); | |
+ mutableStyle->setProperty(CSSPropertyUnicodeBidi, static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent()); | |
+ if (direction) { | |
+ ASSERT(direction->isPrimitiveValue()); | |
+ mutableStyle->setProperty(CSSPropertyDirection, static_cast<CSSPrimitiveValue*>(direction.get())->getIdent()); | |
+ } | |
+ } | |
+ | |
+ // Handle block styles, substracting these from the typing style. | |
+ RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties(); | |
+ blockStyle->diff(mutableStyle.get()); | |
+ if (blockStyle->length() > 0) | |
+ applyCommand(ApplyStyleCommand::create(document(), blockStyle.get(), editingAction)); | |
+ | |
+ // Set the remaining style as the typing style. | |
+ m_typingStyle = mutableStyle.release(); | |
+} | |
+ | |
+String Frame::selectionStartStylePropertyValue(int stylePropertyID) const | |
+{ | |
+ Node *nodeToRemove; | |
+ RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove); | |
+ if (!selectionStyle) | |
+ return String(); | |
+ | |
+ String value = selectionStyle->getPropertyValue(stylePropertyID); | |
+ | |
+ if (nodeToRemove) { | |
+ ExceptionCode ec = 0; | |
+ nodeToRemove->remove(ec); | |
+ ASSERT(!ec); | |
+ } | |
+ | |
+ return value; | |
+} | |
+ | |
+PassRefPtr<CSSComputedStyleDeclaration> Frame::selectionComputedStyle(Node*& nodeToRemove) const | |
+{ | |
+ nodeToRemove = 0; | |
+ | |
+ if (selection()->isNone()) | |
+ return 0; | |
+ | |
+ RefPtr<Range> range(selection()->toNormalizedRange()); | |
+ Position pos = range->editingStartPosition(); | |
+ | |
+ Element *elem = pos.element(); | |
+ if (!elem) | |
+ return 0; | |
+ | |
+ RefPtr<Element> styleElement = elem; | |
+ ExceptionCode ec = 0; | |
+ | |
+ if (m_typingStyle) { | |
+ styleElement = document()->createElement(spanTag, false); | |
+ | |
+ styleElement->setAttribute(styleAttr, m_typingStyle->cssText().impl(), ec); | |
+ ASSERT(!ec); | |
+ | |
+ styleElement->appendChild(document()->createEditingTextNode(""), ec); | |
+ ASSERT(!ec); | |
+ | |
+ if (elem->renderer() && elem->renderer()->canHaveChildren()) { | |
+ elem->appendChild(styleElement, ec); | |
+ } else { | |
+ Node *parent = elem->parent(); | |
+ Node *next = elem->nextSibling(); | |
+ | |
+ if (next) | |
+ parent->insertBefore(styleElement, next, ec); | |
+ else | |
+ parent->appendChild(styleElement, ec); | |
+ } | |
+ ASSERT(!ec); | |
+ | |
+ nodeToRemove = styleElement.get(); | |
+ } | |
+ | |
+ return computedStyle(styleElement.release()); | |
+} | |
+ | |
+void Frame::textFieldDidBeginEditing(Element* e) | |
+{ | |
+ if (editor()->client()) | |
+ editor()->client()->textFieldDidBeginEditing(e); | |
+} | |
+ | |
+void Frame::textFieldDidEndEditing(Element* e) | |
+{ | |
+ if (editor()->client()) | |
+ editor()->client()->textFieldDidEndEditing(e); | |
+} | |
+ | |
+void Frame::textDidChangeInTextField(Element* e) | |
+{ | |
+ if (editor()->client()) | |
+ editor()->client()->textDidChangeInTextField(e); | |
+} | |
+ | |
+bool Frame::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke) | |
+{ | |
+ if (editor()->client()) | |
+ return editor()->client()->doTextFieldCommandFromEvent(e, ke); | |
+ | |
+ return false; | |
+} | |
+ | |
+void Frame::textWillBeDeletedInTextField(Element* input) | |
+{ | |
+ if (editor()->client()) | |
+ editor()->client()->textWillBeDeletedInTextField(input); | |
+} | |
+ | |
+void Frame::textDidChangeInTextArea(Element* e) | |
+{ | |
+ if (editor()->client()) | |
+ editor()->client()->textDidChangeInTextArea(e); | |
+} | |
+ | |
+void Frame::applyEditingStyleToBodyElement() const | |
+{ | |
+ RefPtr<NodeList> list = m_doc->getElementsByTagName("body"); | |
+ unsigned len = list->length(); | |
+ for (unsigned i = 0; i < len; i++) | |
+ applyEditingStyleToElement(static_cast<Element*>(list->item(i))); | |
+} | |
+ | |
+void Frame::removeEditingStyleFromBodyElement() const | |
+{ | |
+ RefPtr<NodeList> list = m_doc->getElementsByTagName("body"); | |
+ unsigned len = list->length(); | |
+ for (unsigned i = 0; i < len; i++) | |
+ removeEditingStyleFromElement(static_cast<Element*>(list->item(i))); | |
+} | |
+ | |
+void Frame::applyEditingStyleToElement(Element* element) const | |
+{ | |
+ if (!element) | |
+ return; | |
+ | |
+ CSSStyleDeclaration* style = element->style(); | |
+ ASSERT(style); | |
+ | |
+ ExceptionCode ec = 0; | |
+ style->setProperty(CSSPropertyWordWrap, "break-word", false, ec); | |
+ ASSERT(!ec); | |
+ style->setProperty(CSSPropertyWebkitNbspMode, "space", false, ec); | |
+ ASSERT(!ec); | |
+ style->setProperty(CSSPropertyWebkitLineBreak, "after-white-space", false, ec); | |
+ ASSERT(!ec); | |
+} | |
+ | |
+void Frame::removeEditingStyleFromElement(Element*) const | |
+{ | |
+} | |
+ | |
+#ifndef NDEBUG | |
+#if PLATFORM(WKC) | |
+static HashSet<Frame*>* gStaticKeepAliveSet = 0; | |
+static HashSet<Frame*>& keepAliveSet() | |
+{ | |
+ if (!gStaticKeepAliveSet) { | |
+ gStaticKeepAliveSet = new HashSet<Frame*>(); | |
+ } | |
+ HashSet<Frame*>& staticKeepAliveSet = *gStaticKeepAliveSet; | |
+ return staticKeepAliveSet; | |
+} | |
+#else | |
+static HashSet<Frame*>& keepAliveSet() | |
+{ | |
+ DEFINE_STATIC_LOCAL(HashSet<Frame*>, staticKeepAliveSet, ()); | |
+ return staticKeepAliveSet; | |
+} | |
+#endif | |
+#endif | |
+ | |
+void Frame::keepAlive() | |
+{ | |
+ if (m_lifeSupportTimer.isActive()) | |
+ return; | |
+#ifndef NDEBUG | |
+ keepAliveSet().add(this); | |
+#endif | |
+ ref(); | |
+ m_lifeSupportTimer.startOneShot(0); | |
+} | |
+ | |
+#ifndef NDEBUG | |
+void Frame::cancelAllKeepAlive() | |
+{ | |
+ HashSet<Frame*>::iterator end = keepAliveSet().end(); | |
+ for (HashSet<Frame*>::iterator it = keepAliveSet().begin(); it != end; ++it) { | |
+ Frame* frame = *it; | |
+ frame->m_lifeSupportTimer.stop(); | |
+ frame->deref(); | |
+ } | |
+ keepAliveSet().clear(); | |
+} | |
+#endif | |
+ | |
+void Frame::lifeSupportTimerFired(Timer<Frame>*) | |
+{ | |
+#ifndef NDEBUG | |
+ keepAliveSet().remove(this); | |
+#endif | |
+ deref(); | |
+} | |
+ | |
+void Frame::clearDOMWindow() | |
+{ | |
+ if (m_domWindow) { | |
+ m_liveFormerWindows.add(m_domWindow.get()); | |
+ m_domWindow->clear(); | |
+ } | |
+ m_domWindow = 0; | |
+} | |
+ | |
+RenderView* Frame::contentRenderer() const | |
+{ | |
+ Document* doc = document(); | |
+ if (!doc) | |
+ return 0; | |
+ RenderObject* object = doc->renderer(); | |
+ if (!object) | |
+ return 0; | |
+ ASSERT(object->isRenderView()); | |
+ return toRenderView(object); | |
+} | |
+ | |
+HTMLFrameOwnerElement* Frame::ownerElement() const | |
+{ | |
+ return m_ownerElement; | |
+} | |
+ | |
+RenderPart* Frame::ownerRenderer() const | |
+{ | |
+ HTMLFrameOwnerElement* ownerElement = m_ownerElement; | |
+ if (!ownerElement) | |
+ return 0; | |
+ RenderObject* object = ownerElement->renderer(); | |
+ if (!object) | |
+ return 0; | |
+ // FIXME: If <object> is ever fixed to disassociate itself from frames | |
+ // that it has started but canceled, then this can turn into an ASSERT | |
+ // since m_ownerElement would be 0 when the load is canceled. | |
+ // https://bugs.webkit.org/show_bug.cgi?id=18585 | |
+ if (!object->isRenderPart()) | |
+ return 0; | |
+ return toRenderPart(object); | |
+} | |
+ | |
+bool Frame::isDisconnected() const | |
+{ | |
+ return m_isDisconnected; | |
+} | |
+ | |
+void Frame::setIsDisconnected(bool isDisconnected) | |
+{ | |
+ m_isDisconnected = isDisconnected; | |
+} | |
+ | |
+bool Frame::excludeFromTextSearch() const | |
+{ | |
+ return m_excludeFromTextSearch; | |
+} | |
+ | |
+void Frame::setExcludeFromTextSearch(bool exclude) | |
+{ | |
+ m_excludeFromTextSearch = exclude; | |
+} | |
+ | |
+// returns FloatRect because going through IntRect would truncate any floats | |
+FloatRect Frame::selectionBounds(bool clipToVisibleContent) const | |
+{ | |
+ m_doc->updateLayout(); | |
+ | |
+ RenderView* root = contentRenderer(); | |
+ FrameView* view = m_view.get(); | |
+ if (!root || !view) | |
+ return IntRect(); | |
+ | |
+ IntRect selectionRect = root->selectionBounds(clipToVisibleContent); | |
+ return clipToVisibleContent ? intersection(selectionRect, view->visibleContentRect()) : selectionRect; | |
+} | |
+ | |
+void Frame::selectionTextRects(Vector<FloatRect>& rects, SelectionRectRespectTransforms respectTransforms, bool clipToVisibleContent) const | |
+{ | |
+ RenderView* root = contentRenderer(); | |
+ if (!root) | |
+ return; | |
+ | |
+ RefPtr<Range> selectedRange = selection()->toNormalizedRange(); | |
+ | |
+ FloatRect visibleContentRect = m_view->visibleContentRect(); | |
+ | |
+ // FIMXE: we are appending empty rects to the list for those that fall outside visibleContentRect. | |
+ // We may not want to do that. | |
+ if (respectTransforms) { | |
+ Vector<FloatQuad> quads; | |
+ selectedRange->textQuads(quads, true); | |
+ | |
+ unsigned size = quads.size(); | |
+ for (unsigned i = 0; i < size; ++i) { | |
+ IntRect currRect = quads[i].enclosingBoundingBox(); | |
+ if (clipToVisibleContent) | |
+ rects.append(intersection(currRect, visibleContentRect)); | |
+ else | |
+ rects.append(currRect); | |
+ } | |
+ } else { | |
+ Vector<IntRect> intRects; | |
+ selectedRange->textRects(intRects, true); | |
+ | |
+ unsigned size = intRects.size(); | |
+ for (unsigned i = 0; i < size; ++i) { | |
+ if (clipToVisibleContent) | |
+ rects.append(intersection(intRects[i], visibleContentRect)); | |
+ else | |
+ rects.append(intRects[i]); | |
+ } | |
+ } | |
+} | |
+ | |
+// Scans logically forward from "start", including any child frames | |
+static HTMLFormElement *scanForForm(Node *start) | |
+{ | |
+ Node *n; | |
+ for (n = start; n; n = n->traverseNextNode()) { | |
+ if (n->hasTagName(formTag)) | |
+ return static_cast<HTMLFormElement*>(n); | |
+ else if (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement()) | |
+ return static_cast<HTMLFormControlElement*>(n)->form(); | |
+ else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) { | |
+ Node *childDoc = static_cast<HTMLFrameElementBase*>(n)->contentDocument(); | |
+ if (HTMLFormElement *frameResult = scanForForm(childDoc)) | |
+ return frameResult; | |
+ } | |
+ } | |
+ return 0; | |
+} | |
+ | |
+// We look for either the form containing the current focus, or for one immediately after it | |
+HTMLFormElement *Frame::currentForm() const | |
+{ | |
+ // start looking either at the active (first responder) node, or where the selection is | |
+ Node *start = m_doc ? m_doc->focusedNode() : 0; | |
+ if (!start) | |
+ start = selection()->start().node(); | |
+ | |
+ // try walking up the node tree to find a form element | |
+ Node *n; | |
+ for (n = start; n; n = n->parentNode()) { | |
+ if (n->hasTagName(formTag)) | |
+ return static_cast<HTMLFormElement*>(n); | |
+ else if (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement()) | |
+ return static_cast<HTMLFormControlElement*>(n)->form(); | |
+ } | |
+ | |
+ // try walking forward in the node tree to find a form element | |
+ return start ? scanForForm(start) : 0; | |
+} | |
+ | |
+void Frame::revealSelection(const ScrollAlignment& alignment, bool revealExtent) | |
+{ | |
+ IntRect rect; | |
+ | |
+ switch (selection()->selectionType()) { | |
+ case VisibleSelection::NoSelection: | |
+ return; | |
+ case VisibleSelection::CaretSelection: | |
+ rect = selection()->absoluteCaretBounds(); | |
+ break; | |
+ case VisibleSelection::RangeSelection: | |
+ rect = revealExtent ? VisiblePosition(selection()->extent()).absoluteCaretBounds() : enclosingIntRect(selectionBounds(false)); | |
+ break; | |
+ } | |
+ | |
+ Position start = selection()->start(); | |
+ ASSERT(start.node()); | |
+ if (start.node() && start.node()->renderer()) { | |
+ // FIXME: This code only handles scrolling the startContainer's layer, but | |
+ // the selection rect could intersect more than just that. | |
+ // See <rdar://problem/4799899>. | |
+ if (RenderLayer* layer = start.node()->renderer()->enclosingLayer()) | |
+ layer->scrollRectToVisible(rect, false, alignment, alignment); | |
+ } | |
+} | |
+ | |
+Frame* Frame::frameForWidget(const Widget* widget) | |
+{ | |
+ ASSERT_ARG(widget, widget); | |
+ | |
+ if (RenderWidget* renderer = RenderWidget::find(widget)) | |
+ if (Node* node = renderer->node()) | |
+ return node->document()->frame(); | |
+ | |
+ // Assume all widgets are either a FrameView or owned by a RenderWidget. | |
+ // FIXME: That assumption is not right for scroll bars! | |
+ ASSERT(widget->isFrameView()); | |
+ return static_cast<const FrameView*>(widget)->frame(); | |
+} | |
+ | |
+void Frame::clearTimers(FrameView *view, Document *document) | |
+{ | |
+ if (view) { | |
+ view->unscheduleRelayout(); | |
+ if (view->frame()) { | |
+ view->frame()->animation()->suspendAnimations(document); | |
+ view->frame()->eventHandler()->stopAutoscrollTimer(); | |
+ } | |
+ } | |
+} | |
+ | |
+void Frame::clearTimers() | |
+{ | |
+ clearTimers(m_view.get(), document()); | |
+} | |
+ | |
+RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const | |
+{ | |
+ nodeToRemove = 0; | |
+ | |
+ if (selection()->isNone()) | |
+ return 0; | |
+ | |
+ Position pos = selection()->selection().visibleStart().deepEquivalent(); | |
+ if (!pos.isCandidate()) | |
+ return 0; | |
+ Node *node = pos.node(); | |
+ if (!node) | |
+ return 0; | |
+ | |
+ if (!m_typingStyle) | |
+ return node->renderer()->style(); | |
+ | |
+ RefPtr<Element> styleElement = document()->createElement(spanTag, false); | |
+ | |
+ ExceptionCode ec = 0; | |
+ String styleText = m_typingStyle->cssText() + " display: inline"; | |
+ styleElement->setAttribute(styleAttr, styleText.impl(), ec); | |
+ ASSERT(!ec); | |
+ | |
+ styleElement->appendChild(document()->createEditingTextNode(""), ec); | |
+ ASSERT(!ec); | |
+ | |
+ node->parentNode()->appendChild(styleElement, ec); | |
+ ASSERT(!ec); | |
+ | |
+ nodeToRemove = styleElement.get(); | |
+ return styleElement->renderer() ? styleElement->renderer()->style() : 0; | |
+} | |
+ | |
+void Frame::setSelectionFromNone() | |
+{ | |
+ // Put a caret inside the body if the entire frame is editable (either the | |
+ // entire WebView is editable or designMode is on for this document). | |
+ Document *doc = document(); | |
+ bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); | |
+ if (!selection()->isNone() || !(isContentEditable() || caretBrowsing)) | |
+ return; | |
+ | |
+ Node* node = doc->documentElement(); | |
+ while (node && !node->hasTagName(bodyTag)) | |
+ node = node->traverseNextNode(); | |
+ if (node) | |
+ selection()->setSelection(VisibleSelection(Position(node, 0), DOWNSTREAM)); | |
+} | |
+ | |
+bool Frame::inViewSourceMode() const | |
+{ | |
+ return m_inViewSourceMode; | |
+} | |
+ | |
+void Frame::setInViewSourceMode(bool mode) | |
+{ | |
+ m_inViewSourceMode = mode; | |
+} | |
+ | |
+// Searches from the beginning of the document if nothing is selected. | |
+bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection) | |
+{ | |
+ if (target.isEmpty()) | |
+ return false; | |
+ | |
+ if (excludeFromTextSearch()) | |
+ return false; | |
+ | |
+ // Start from an edge of the selection, if there's a selection that's not in shadow content. Which edge | |
+ // is used depends on whether we're searching forward or backward, and whether startInSelection is set. | |
+ RefPtr<Range> searchRange(rangeOfContents(document())); | |
+ VisibleSelection selection = this->selection()->selection(); | |
+ | |
+ if (forward) | |
+ setStart(searchRange.get(), startInSelection ? selection.visibleStart() : selection.visibleEnd()); | |
+ else | |
+ setEnd(searchRange.get(), startInSelection ? selection.visibleEnd() : selection.visibleStart()); | |
+ | |
+ Node* shadowTreeRoot = selection.shadowTreeRootNode(); | |
+ if (shadowTreeRoot) { | |
+ ExceptionCode ec = 0; | |
+ if (forward) | |
+ searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec); | |
+ else | |
+ searchRange->setStart(shadowTreeRoot, 0, ec); | |
+ } | |
+ | |
+ RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, forward, caseFlag)); | |
+ // If we started in the selection and the found range exactly matches the existing selection, find again. | |
+ // Build a selection with the found range to remove collapsed whitespace. | |
+ // Compare ranges instead of selection objects to ignore the way that the current selection was made. | |
+ if (startInSelection && *VisibleSelection(resultRange.get()).toNormalizedRange() == *selection.toNormalizedRange()) { | |
+ searchRange = rangeOfContents(document()); | |
+ if (forward) | |
+ setStart(searchRange.get(), selection.visibleEnd()); | |
+ else | |
+ setEnd(searchRange.get(), selection.visibleStart()); | |
+ | |
+ if (shadowTreeRoot) { | |
+ ExceptionCode ec = 0; | |
+ if (forward) | |
+ searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec); | |
+ else | |
+ searchRange->setStart(shadowTreeRoot, 0, ec); | |
+ } | |
+ | |
+ resultRange = findPlainText(searchRange.get(), target, forward, caseFlag); | |
+ } | |
+ | |
+ ExceptionCode exception = 0; | |
+ | |
+ // If nothing was found in the shadow tree, search in main content following the shadow tree. | |
+ if (resultRange->collapsed(exception) && shadowTreeRoot) { | |
+ searchRange = rangeOfContents(document()); | |
+ if (forward) | |
+ searchRange->setStartAfter(shadowTreeRoot->shadowParentNode(), exception); | |
+ else | |
+ searchRange->setEndBefore(shadowTreeRoot->shadowParentNode(), exception); | |
+ | |
+ resultRange = findPlainText(searchRange.get(), target, forward, caseFlag); | |
+ } | |
+ | |
+ if (!editor()->insideVisibleArea(resultRange.get())) { | |
+ resultRange = editor()->nextVisibleRange(resultRange.get(), target, forward, caseFlag, wrapFlag); | |
+ if (!resultRange) | |
+ return false; | |
+ } | |
+ | |
+ // If we didn't find anything and we're wrapping, search again in the entire document (this will | |
+ // redundantly re-search the area already searched in some cases). | |
+ if (resultRange->collapsed(exception) && wrapFlag) { | |
+ searchRange = rangeOfContents(document()); | |
+ resultRange = findPlainText(searchRange.get(), target, forward, caseFlag); | |
+ // We used to return false here if we ended up with the same range that we started with | |
+ // (e.g., the selection was already the only instance of this text). But we decided that | |
+ // this should be a success case instead, so we'll just fall through in that case. | |
+ } | |
+ | |
+ if (resultRange->collapsed(exception)) | |
+ return false; | |
+ | |
+ this->selection()->setSelection(VisibleSelection(resultRange.get(), DOWNSTREAM)); | |
+ revealSelection(); | |
+ return true; | |
+} | |
+ | |
+unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsigned limit) | |
+{ | |
+ if (target.isEmpty()) | |
+ return 0; | |
+ | |
+ RefPtr<Range> searchRange(rangeOfContents(document())); | |
+ | |
+ ExceptionCode exception = 0; | |
+ unsigned matchCount = 0; | |
+ do { | |
+ RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag)); | |
+ if (resultRange->collapsed(exception)) { | |
+ if (!resultRange->startContainer()->isInShadowTree()) | |
+ break; | |
+ | |
+ searchRange = rangeOfContents(document()); | |
+ searchRange->setStartAfter(resultRange->startContainer()->shadowAncestorNode(), exception); | |
+ continue; | |
+ } | |
+ | |
+ // A non-collapsed result range can in some funky whitespace cases still not | |
+ // advance the range's start position (4509328). Break to avoid infinite loop. | |
+ VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM); | |
+ if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM)) | |
+ break; | |
+ | |
+ // Only treat the result as a match if it is visible | |
+ if (editor()->insideVisibleArea(resultRange.get())) { | |
+ ++matchCount; | |
+ document()->addMarker(resultRange.get(), DocumentMarker::TextMatch); | |
+ } | |
+ | |
+ // Stop looking if we hit the specified limit. A limit of 0 means no limit. | |
+ if (limit > 0 && matchCount >= limit) | |
+ break; | |
+ | |
+ setStart(searchRange.get(), newStart); | |
+ Node* shadowTreeRoot = searchRange->shadowTreeRootNode(); | |
+ if (searchRange->collapsed(exception) && shadowTreeRoot) | |
+ searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), exception); | |
+ } while (true); | |
+ | |
+ // Do a "fake" paint in order to execute the code that computes the rendered rect for | |
+ // each text match. | |
+ Document* doc = document(); | |
+ if (m_view && contentRenderer()) { | |
+ doc->updateLayout(); // Ensure layout is up to date. | |
+ IntRect visibleRect = m_view->visibleContentRect(); | |
+ if (!visibleRect.isEmpty()) { | |
+ GraphicsContext context((PlatformGraphicsContext*)0); | |
+ context.setPaintingDisabled(true); | |
+ m_view->paintContents(&context, visibleRect); | |
+ } | |
+ } | |
+ | |
+ return matchCount; | |
+} | |
+ | |
+bool Frame::markedTextMatchesAreHighlighted() const | |
+{ | |
+ return m_highlightTextMatches; | |
+} | |
+ | |
+void Frame::setMarkedTextMatchesAreHighlighted(bool flag) | |
+{ | |
+ if (flag == m_highlightTextMatches) | |
+ return; | |
+ | |
+ m_highlightTextMatches = flag; | |
+ document()->repaintMarkers(DocumentMarker::TextMatch); | |
+} | |
+ | |
+FrameTree* Frame::tree() const | |
+{ | |
+ return &m_treeNode; | |
+} | |
+ | |
+void Frame::setDOMWindow(DOMWindow* domWindow) | |
+{ | |
+ if (m_domWindow) { | |
+ m_liveFormerWindows.add(m_domWindow.get()); | |
+ m_domWindow->clear(); | |
+ } | |
+ m_domWindow = domWindow; | |
+} | |
+ | |
+DOMWindow* Frame::domWindow() const | |
+{ | |
+ if (!m_domWindow) | |
+ m_domWindow = DOMWindow::create(const_cast<Frame*>(this)); | |
+ | |
+ return m_domWindow.get(); | |
+} | |
+ | |
+void Frame::clearFormerDOMWindow(DOMWindow* window) | |
+{ | |
+ m_liveFormerWindows.remove(window); | |
+} | |
+ | |
+Page* Frame::page() const | |
+{ | |
+ return m_page; | |
+} | |
+ | |
+void Frame::detachFromPage() | |
+{ | |
+ m_page = 0; | |
+} | |
+ | |
+EventHandler* Frame::eventHandler() const | |
+{ | |
+ return &m_eventHandler; | |
+} | |
+ | |
+void Frame::pageDestroyed() | |
+{ | |
+ if (Frame* parent = tree()->parent()) | |
+ parent->loader()->checkLoadComplete(); | |
+ | |
+ // FIXME: It's unclear as to why this is called more than once, but it is, | |
+ // so page() could be NULL. | |
+ if (page() && page()->focusController()->focusedFrame() == this) | |
+ page()->focusController()->setFocusedFrame(0); | |
+ | |
+ script()->clearWindowShell(); | |
+ script()->clearScriptObjects(); | |
+ script()->updatePlatformScriptObjects(); | |
+ | |
+ detachFromPage(); | |
+} | |
+ | |
+void Frame::disconnectOwnerElement() | |
+{ | |
+ if (m_ownerElement) { | |
+ if (Document* doc = document()) | |
+ doc->clearAXObjectCache(); | |
+ m_ownerElement->m_contentFrame = 0; | |
+ if (m_page) | |
+ m_page->decrementFrameCount(); | |
+ } | |
+ m_ownerElement = 0; | |
+} | |
+ | |
+String Frame::documentTypeString() const | |
+{ | |
+ if (DocumentType* doctype = document()->doctype()) | |
+ return createMarkup(doctype); | |
+ | |
+ return String(); | |
+} | |
+ | |
+void Frame::focusWindow() | |
+{ | |
+ if (!page()) | |
+ return; | |
+ | |
+ // If we're a top level window, bring the window to the front. | |
+ if (!tree()->parent()) | |
+ page()->chrome()->focus(); | |
+ | |
+ eventHandler()->focusDocumentView(); | |
+} | |
+ | |
+void Frame::unfocusWindow() | |
+{ | |
+ if (!page()) | |
+ return; | |
+ | |
+ // If we're a top level window, deactivate the window. | |
+ if (!tree()->parent()) | |
+ page()->chrome()->unfocus(); | |
+} | |
+ | |
+bool Frame::shouldClose() | |
+{ | |
+ Chrome* chrome = page() ? page()->chrome() : 0; | |
+ if (!chrome || !chrome->canRunBeforeUnloadConfirmPanel()) | |
+ return true; | |
+ | |
+ if (!m_domWindow) | |
+ return true; | |
+ | |
+ RefPtr<Document> doc = document(); | |
+ HTMLElement* body = doc->body(); | |
+ if (!body) | |
+ return true; | |
+ | |
+ RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create(); | |
+ m_domWindow->dispatchEvent(beforeUnloadEvent.get(), m_domWindow->document()); | |
+ | |
+ if (!beforeUnloadEvent->defaultPrevented()) | |
+ doc->defaultEventHandler(beforeUnloadEvent.get()); | |
+ if (beforeUnloadEvent->result().isNull()) | |
+ return true; | |
+ | |
+ String text = doc->displayStringModifiedByEncoding(beforeUnloadEvent->result()); | |
+ return chrome->runBeforeUnloadConfirmPanel(text, this); | |
+} | |
+ | |
+void Frame::scheduleClose() | |
+{ | |
+ if (!shouldClose()) | |
+ return; | |
+ | |
+ Chrome* chrome = page() ? page()->chrome() : 0; | |
+ if (chrome) | |
+ chrome->closeWindowSoon(); | |
+} | |
+ | |
+void Frame::respondToChangedSelection(const VisibleSelection& oldSelection, bool closeTyping) | |
+{ | |
+ bool isContinuousSpellCheckingEnabled = editor()->isContinuousSpellCheckingEnabled(); | |
+ bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && editor()->isGrammarCheckingEnabled(); | |
+ if (isContinuousSpellCheckingEnabled) { | |
+ VisibleSelection newAdjacentWords; | |
+ VisibleSelection newSelectedSentence; | |
+ bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); | |
+ if (selection()->selection().isContentEditable() || caretBrowsing) { | |
+ VisiblePosition newStart(selection()->selection().visibleStart()); | |
+ newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary)); | |
+ if (isContinuousGrammarCheckingEnabled) | |
+ newSelectedSentence = VisibleSelection(startOfSentence(newStart), endOfSentence(newStart)); | |
+ } | |
+ | |
+ // When typing we check spelling elsewhere, so don't redo it here. | |
+ // If this is a change in selection resulting from a delete operation, | |
+ // oldSelection may no longer be in the document. | |
+ if (closeTyping && oldSelection.isContentEditable() && oldSelection.start().node() && oldSelection.start().node()->inDocument()) { | |
+ VisiblePosition oldStart(oldSelection.visibleStart()); | |
+ VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary)); | |
+ if (oldAdjacentWords != newAdjacentWords) { | |
+ if (isContinuousGrammarCheckingEnabled) { | |
+ VisibleSelection oldSelectedSentence = VisibleSelection(startOfSentence(oldStart), endOfSentence(oldStart)); | |
+ editor()->markMisspellingsAndBadGrammar(oldAdjacentWords, oldSelectedSentence != newSelectedSentence, oldSelectedSentence); | |
+ } else | |
+ editor()->markMisspellingsAndBadGrammar(oldAdjacentWords, false, oldAdjacentWords); | |
+ } | |
+ } | |
+ | |
+ // This only erases markers that are in the first unit (word or sentence) of the selection. | |
+ // Perhaps peculiar, but it matches AppKit. | |
+ if (RefPtr<Range> wordRange = newAdjacentWords.toNormalizedRange()) | |
+ document()->removeMarkers(wordRange.get(), DocumentMarker::Spelling); | |
+ if (RefPtr<Range> sentenceRange = newSelectedSentence.toNormalizedRange()) | |
+ document()->removeMarkers(sentenceRange.get(), DocumentMarker::Grammar); | |
+ } | |
+ | |
+ // When continuous spell checking is off, existing markers disappear after the selection changes. | |
+ if (!isContinuousSpellCheckingEnabled) | |
+ document()->removeMarkers(DocumentMarker::Spelling); | |
+ if (!isContinuousGrammarCheckingEnabled) | |
+ document()->removeMarkers(DocumentMarker::Grammar); | |
+ | |
+ editor()->respondToChangedSelection(oldSelection); | |
+} | |
+ | |
+VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint) | |
+{ | |
+ HitTestResult result = eventHandler()->hitTestResultAtPoint(framePoint, true); | |
+ Node* node = result.innerNode(); | |
+ if (!node) | |
+ return VisiblePosition(); | |
+ RenderObject* renderer = node->renderer(); | |
+ if (!renderer) | |
+ return VisiblePosition(); | |
+ VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint()); | |
+ if (visiblePos.isNull()) | |
+ visiblePos = VisiblePosition(Position(node, 0)); | |
+ return visiblePos; | |
+} | |
+ | |
+Document* Frame::documentAtPoint(const IntPoint& point) | |
+{ | |
+ if (!view()) | |
+ return 0; | |
+ | |
+ IntPoint pt = view()->windowToContents(point); | |
+ HitTestResult result = HitTestResult(pt); | |
+ | |
+ if (contentRenderer()) | |
+ result = eventHandler()->hitTestResultAtPoint(pt, false); | |
+ return result.innerNode() ? result.innerNode()->document() : 0; | |
+} | |
+ | |
+void Frame::createView(const IntSize& viewportSize, | |
+ const Color& backgroundColor, bool transparent, | |
+ const IntSize& fixedLayoutSize, bool useFixedLayout, | |
+ ScrollbarMode horizontalScrollbarMode, ScrollbarMode verticalScrollbarMode) | |
+{ | |
+ ASSERT(this); | |
+ ASSERT(m_page); | |
+ | |
+ bool isMainFrame = this == m_page->mainFrame(); | |
+ | |
+ if (isMainFrame && view()) | |
+ view()->setParentVisible(false); | |
+ | |
+ setView(0); | |
+ | |
+ RefPtr<FrameView> frameView; | |
+ if (isMainFrame) { | |
+ frameView = FrameView::create(this, viewportSize); | |
+ frameView->setFixedLayoutSize(fixedLayoutSize); | |
+ frameView->setUseFixedLayout(useFixedLayout); | |
+ } else | |
+ frameView = FrameView::create(this); | |
+ | |
+ frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode); | |
+ | |
+ setView(frameView); | |
+ | |
+ if (backgroundColor.isValid()) | |
+ frameView->updateBackgroundRecursively(backgroundColor, transparent); | |
+ | |
+ if (isMainFrame) | |
+ frameView->setParentVisible(true); | |
+ | |
+ if (ownerRenderer()) | |
+ ownerRenderer()->setWidget(frameView); | |
+ | |
+ if (HTMLFrameOwnerElement* owner = ownerElement()) | |
+ view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff); | |
+} | |
+ | |
+#if PLATFORM(WKC) | |
+void Frame::deleteSharedInstance() | |
+{ | |
+ HTMLNames::finalize(); | |
+#if ENABLE(SVG) | |
+ SVGNames::finalize(); | |
+ XLinkNames::finalize(); | |
+#endif | |
+ | |
+#if ENABLE(WML) | |
+ WMLNames::finalize(); | |
+#endif | |
+ | |
+#if ENABLE(MATHML) | |
+ MathMLNames::finalize(); | |
+#endif | |
+ XMLNames::finalize(); | |
+ | |
+ delete gWordRegExp; | |
+#ifndef NDEBUG | |
+ delete gStaticKeepAliveSet; | |
+ delete gFrameCounter; | |
+#endif | |
+} | |
+ | |
+void Frame::resetVariables() | |
+{ | |
+ HTMLNames::finalize(); | |
+#if ENABLE(SVG) | |
+ SVGNames::finalize(); | |
+ XLinkNames::finalize(); | |
+#endif | |
+ | |
+#if ENABLE(WML) | |
+ WMLNames::finalize(); | |
+#endif | |
+ | |
+#if ENABLE(MATHML) | |
+ MathMLNames::finalize(); | |
+#endif | |
+ XMLNames::finalize(); | |
+ | |
+ gWordRegExp = 0; | |
+ gAlreadyInSelectionLayoutChanged = 0; | |
+#ifndef NDEBUG | |
+ gStaticKeepAliveSet = 0; | |
+ gFrameCounter = 0; | |
+#endif | |
+} | |
+#endif | |
+ | |
+#if ENABLE(WKC_FRAME_FLATTENING) | |
+void Frame::invalidateOwnerRendererLayoutIfNeeded() | |
+{ | |
+ if (settings() && settings()->flatFrameSetLayoutEnabled() && ownerRenderer()) | |
+ ownerRenderer()->setNeedsLayout(true, true); | |
+} | |
+ | |
+bool Frame::isFrameSet() const | |
+{ | |
+ Document* doc = m_doc.get(); | |
+ if (!doc || !doc->isHTMLDocument()) | |
+ return false; | |
+ Node *body = static_cast<HTMLDocument*>(doc)->body(); | |
+ return body && body->renderer() && body->hasTagName(framesetTag); | |
+} | |
+ | |
+#endif | |
+} // namespace WebCore | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/FrameView.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/FrameView.cpp | |
index a850d7c..7f024b9 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/FrameView.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/FrameView.cpp | |
@@ -3,7 +3,7 @@ | |
* 1999 Lars Knoll <knoll@kde.org> | |
* 1999 Antti Koivisto <koivisto@kde.org> | |
* 2000 Dirk Mueller <mueller@kde.org> | |
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | |
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. | |
* (C) 2006 Graham Dennis (graham.dennis@gmail.com) | |
* (C) 2006 Alexey Proskuryakov (ap@nypop.com) | |
* Copyright (C) 2009 Google Inc. All rights reserved. | |
@@ -568,7 +568,9 @@ void FrameView::layout(bool allowSubtree) | |
m_layoutRoot = 0; | |
} | |
+#if !PLATFORM(WKC) | |
ASSERT(m_frame->view() == this); | |
+#endif | |
// This early return should be removed when rdar://5598072 is resolved. In the meantime, there is a | |
// gigantic CrashTracer because of this issue, and the early return will hopefully cause graceful | |
// failure instead. | |
@@ -1326,7 +1328,8 @@ bool FrameView::needsLayout() const | |
|| m_layoutRoot | |
|| (document && document->childNeedsStyleRecalc()) // can occur when using WebKit ObjC interface | |
|| m_frame->needsReapplyStyles() | |
- || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred); | |
+ || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred) | |
+ || m_frame->selection()->needsDisplayUpdate(); | |
} | |
void FrameView::setNeedsLayout() | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/History.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/History.cpp | |
index e45ae6e..c31735f 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/History.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/History.cpp | |
@@ -104,7 +104,12 @@ void History::stateObjectAdded(PassRefPtr<SerializedScriptValue> data, const Str | |
{ | |
if (!m_frame) | |
return; | |
+#if !PLATFORM(WKC) | |
ASSERT(m_frame->page()); | |
+#else | |
+ if (!m_frame->page()) | |
+ return; | |
+#endif | |
KURL fullURL = urlForState(urlString); | |
#if 1 | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/Page.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/Page.cpp | |
index 04b46c1..3ef92fb 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/page/Page.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/page/Page.cpp | |
@@ -406,7 +406,10 @@ void Page::refreshPlugins(bool reload) | |
HashSet<Page*>::iterator end = allPages->end(); | |
for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) { | |
- (*it)->m_pluginData = 0; | |
+ if ((*it)->m_pluginData) { | |
+ (*it)->m_pluginData->disconnectPage(); | |
+ (*it)->m_pluginData = 0; | |
+ } | |
if (reload) { | |
for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) { | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/platform/KURL.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/platform/KURL.cpp | |
index a6b5bc6..bc579f1 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/platform/KURL.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/platform/KURL.cpp | |
@@ -221,6 +221,7 @@ static const unsigned invalidPortNumber = 0xFFFF; | |
static int copyPathRemovingDots(char* dst, const char* src, int srcStart, int srcEnd); | |
static void encodeRelativeString(const String& rel, const TextEncoding&, CharBuffer& ouput); | |
static String substituteBackslashes(const String&); | |
+static bool isValidProtocol(const String&); | |
static inline bool isSchemeFirstChar(char c) { return characterClassTable[static_cast<unsigned char>(c)] & SchemeFirstChar; } | |
static inline bool isSchemeFirstChar(UChar c) { return c <= 0xff && (characterClassTable[c] & SchemeFirstChar); } | |
@@ -581,9 +582,9 @@ unsigned short KURL::port() const | |
{ | |
#if 1 | |
// modified at webkit.org trunk r56879 | |
- // We return a port of 0 if there is no port specified. This can happen in two situations: | |
- // 1) The URL contains no colon after the host name and before the path component of the URL. | |
- // 2) The URL contains a colon but there's no port number before the path component of the URL begins. | |
+ // We return a port of 0 if there is no port specified. This can happen in two situations: | |
+ // 1) The URL contains no colon after the host name and before the path component of the URL. | |
+ // 2) The URL contains a colon but there's no port number before the path component of the URL begins. | |
if (m_hostEnd == m_portEnd || m_hostEnd == m_portEnd - 1) | |
#else | |
if (m_hostEnd == m_portEnd) | |
@@ -592,10 +593,10 @@ unsigned short KURL::port() const | |
#if 1 | |
// modified at webkit.org trunk r56489 and r56492 | |
- const UChar* stringData = m_string.characters(); | |
- bool ok = false; | |
- unsigned number = charactersToUIntStrict(stringData + m_hostEnd + 1, m_portEnd - m_hostEnd - 1, &ok); | |
- if (!ok || number > maximumValidPortNumber) | |
+ const UChar* stringData = m_string.characters(); | |
+ bool ok = false; | |
+ unsigned number = charactersToUIntStrict(stringData + m_hostEnd + 1, m_portEnd - m_hostEnd - 1, &ok); | |
+ if (!ok || number > maximumValidPortNumber) | |
return invalidPortNumber; | |
#else | |
int number = m_string.substring(m_hostEnd + 1, m_portEnd - m_hostEnd - 1).toInt(); | |
@@ -687,17 +688,22 @@ String KURL::path() const | |
return decodeURLEscapeSequences(m_string.substring(m_portEnd, m_pathEnd - m_portEnd)); | |
} | |
-void KURL::setProtocol(const String& s) | |
+bool KURL::setProtocol(const String& s) | |
{ | |
- // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations, | |
- // and to avoid changing more than just the protocol. | |
+ // Firefox and IE remove everything after the first ':'. | |
+ int separatorPosition = s.find(':'); | |
+ String newProtocol = s.substring(0, separatorPosition); | |
+ | |
+ if (!isValidProtocol(newProtocol)) | |
+ return false; | |
if (!m_isValid) { | |
- parse(s + ":" + m_string); | |
- return; | |
+ parse(newProtocol + ":" + m_string); | |
+ return true; | |
} | |
- parse(s + m_string.substring(m_schemeEnd)); | |
+ parse(newProtocol + m_string.substring(m_schemeEnd)); | |
+ return true; | |
} | |
void KURL::setHost(const String& s) | |
@@ -1658,6 +1664,9 @@ bool protocolIsJavaScript(const String& url) | |
bool isValidProtocol(const String& protocol) | |
{ | |
+ // RFC3986: ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) | |
+ if (protocol.isEmpty()) | |
+ return false; | |
if (!isSchemeFirstChar(protocol[0])) | |
return false; | |
unsigned protocolLength = protocol.length(); | |
@@ -1772,10 +1781,10 @@ bool portAllowed(const KURL& url) | |
6000, // X11 | |
#if 1 | |
// added at webkit.org trunk r54193 | |
- 6665, // Alternate IRC [Apple addition] | |
- 6666, // Alternate IRC [Apple addition] | |
- 6667, // Standard IRC [Apple addition] | |
- 6668, // Alternate IRC [Apple addition] | |
+ 6665, // Alternate IRC [Apple addition] | |
+ 6666, // Alternate IRC [Apple addition] | |
+ 6667, // Standard IRC [Apple addition] | |
+ 6668, // Alternate IRC [Apple addition] | |
6669, // Alternate IRC [Apple addition] | |
// added at webkit.org trunk r56489 | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/platform/KURL.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/platform/KURL.h | |
index c4429ea..197d2cb 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/platform/KURL.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/platform/KURL.h | |
@@ -149,7 +149,7 @@ public: | |
bool protocolInHTTPFamily() const; | |
bool isLocalFile() const; | |
- void setProtocol(const String&); | |
+ bool setProtocol(const String&); | |
void setHost(const String&); | |
void removePort(); | |
@@ -278,7 +278,6 @@ const KURL& blankURL(); | |
bool protocolIs(const String& url, const char* protocol); | |
bool protocolIsJavaScript(const String& url); | |
-bool isValidProtocol(const String& protocol); | |
bool isDefaultPortForProtocol(unsigned short port, const String& protocol); | |
bool portAllowed(const KURL&); // Blacklist ports that should never be used for Web resources. | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/platform/LinkHash.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/platform/LinkHash.cpp | |
index 878933a..5a93413 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/platform/LinkHash.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/platform/LinkHash.cpp | |
@@ -31,36 +31,36 @@ | |
namespace WebCore { | |
-static inline int findSlashDotDotSlash(const UChar* characters, size_t length) | |
+static inline int findSlashDotDotSlash(const UChar* characters, size_t length, size_t position) | |
{ | |
if (length < 4) | |
return -1; | |
- unsigned loopLimit = length - 3; | |
- for (unsigned i = 0; i < loopLimit; ++i) { | |
+ size_t loopLimit = length - 3; | |
+ for (size_t i = position; i < loopLimit; ++i) { | |
if (characters[i] == '/' && characters[i + 1] == '.' && characters[i + 2] == '.' && characters[i + 3] == '/') | |
return i; | |
} | |
return -1; | |
} | |
-static inline int findSlashSlash(const UChar* characters, size_t length, int position) | |
+static inline int findSlashSlash(const UChar* characters, size_t length, size_t position) | |
{ | |
if (length < 2) | |
return -1; | |
- unsigned loopLimit = length - 1; | |
- for (unsigned i = position; i < loopLimit; ++i) { | |
+ size_t loopLimit = length - 1; | |
+ for (size_t i = position; i < loopLimit; ++i) { | |
if (characters[i] == '/' && characters[i + 1] == '/') | |
return i; | |
} | |
return -1; | |
} | |
-static inline int findSlashDotSlash(const UChar* characters, size_t length) | |
+static inline int findSlashDotSlash(const UChar* characters, size_t length, size_t position) | |
{ | |
if (length < 3) | |
return -1; | |
- unsigned loopLimit = length - 2; | |
- for (unsigned i = 0; i < loopLimit; ++i) { | |
+ size_t loopLimit = length - 2; | |
+ for (size_t i = position; i < loopLimit; ++i) { | |
if (characters[i] == '/' && characters[i + 1] == '.' && characters[i + 2] == '/') | |
return i; | |
} | |
@@ -79,42 +79,90 @@ static inline bool containsColonSlashSlash(const UChar* characters, unsigned len | |
return false; | |
} | |
-static inline void cleanPath(Vector<UChar, 512>& path) | |
+static inline void squeezeOutNullCharacters(Vector<UChar, 512>& string) | |
{ | |
- // FIXME: Shold not do this in the query or anchor part. | |
- int pos; | |
- while ((pos = findSlashDotDotSlash(path.data(), path.size())) != -1) { | |
- int prev = reverseFind(path.data(), path.size(), '/', pos - 1); | |
- // don't remove the host, i.e. http://foo.org/../foo.html | |
- if (prev < 0 || (prev > 3 && path[prev - 2] == ':' && path[prev - 1] == '/')) | |
- path.remove(pos, 3); | |
- else | |
- path.remove(prev, pos - prev + 3); | |
+ size_t size = string.size(); | |
+ size_t i = 0; | |
+ for (i = 0; i < size; ++i) { | |
+ if (!string[i]) | |
+ break; | |
} | |
+ if (i == size) | |
+ return; | |
+ size_t j = i; | |
+ for (++i; i < size; ++i) { | |
+ if (UChar character = string[i]) | |
+ string[j++] = character; | |
+ } | |
+ ASSERT(j < size); | |
+ string.shrink(j); | |
+} | |
- // FIXME: Shold not do this in the query part. | |
- // Set refPos to -2 to mean "I haven't looked for the anchor yet". | |
- // We don't want to waste a function call on the search for the the anchor | |
- // in the vast majority of cases where there is no "//" in the path. | |
- pos = 0; | |
- int refPos = -2; | |
- while ((pos = findSlashSlash(path.data(), path.size(), pos)) != -1) { | |
- if (refPos == -2) | |
- refPos = find(path.data(), path.size(), '#'); | |
- if (refPos > 0 && pos >= refPos) | |
- break; | |
+static void cleanSlashDotDotSlashes(Vector<UChar, 512>& path, size_t firstSlash) | |
+{ | |
+ size_t slash = firstSlash; | |
+ do { | |
+ size_t previousSlash = slash ? reverseFind(path.data(), path.size(), '/', slash - 1) : notFound; | |
+ // Don't remove the host, i.e. http://foo.org/../foo.html | |
+ if (previousSlash == notFound || (previousSlash > 3 && path[previousSlash - 2] == ':' && path[previousSlash - 1] == '/')) { | |
+ path[slash] = 0; | |
+ path[slash + 1] = 0; | |
+ path[slash + 2] = 0; | |
+ } else { | |
+ for (size_t i = previousSlash; i < slash + 3; ++i) | |
+ path[i] = 0; | |
+ } | |
+ slash += 3; | |
+ } while ((slash = findSlashDotDotSlash(path.data(), path.size(), slash)) != notFound); | |
+ squeezeOutNullCharacters(path); | |
+} | |
+ | |
+static void mergeDoubleSlashes(Vector<UChar, 512>& path, size_t firstSlash) | |
+{ | |
+ size_t refPos = find(path.data(), path.size(), '#'); | |
+ if (!refPos || refPos == notFound) | |
+ refPos = path.size(); | |
- if (pos == 0 || path[pos - 1] != ':') | |
- path.remove(pos); | |
+ size_t slash = firstSlash; | |
+ while (slash < refPos) { | |
+ if (!slash || path[slash - 1] != ':') | |
+ path[slash++] = 0; | |
else | |
- pos += 2; | |
+ slash += 2; | |
+ if ((slash = findSlashSlash(path.data(), path.size(), slash)) == notFound) | |
+ break; | |
} | |
+ squeezeOutNullCharacters(path); | |
+} | |
- // FIXME: Shold not do this in the query or anchor part. | |
- while ((pos = findSlashDotSlash(path.data(), path.size())) != -1) | |
- path.remove(pos, 2); | |
+static void cleanSlashDotSlashes(Vector<UChar, 512>& path, size_t firstSlash) | |
+{ | |
+ size_t slash = firstSlash; | |
+ do { | |
+ path[slash] = 0; | |
+ path[slash + 1] = 0; | |
+ slash += 2; | |
+ } while ((slash = findSlashDotSlash(path.data(), path.size(), slash)) != notFound); | |
+ squeezeOutNullCharacters(path); | |
} | |
+static inline void cleanPath(Vector<UChar, 512>& path) | |
+{ | |
+ // FIXME: Should not do this in the query or anchor part of the URL. | |
+ size_t firstSlash = findSlashDotDotSlash(path.data(), path.size(), 0); | |
+ if (firstSlash != notFound) | |
+ cleanSlashDotDotSlashes(path, firstSlash); | |
+ | |
+ // FIXME: Should not do this in the query part. | |
+ firstSlash = findSlashSlash(path.data(), path.size(), 0); | |
+ if (firstSlash != notFound) | |
+ mergeDoubleSlashes(path, firstSlash); | |
+ | |
+ // FIXME: Should not do this in the query or anchor part. | |
+ firstSlash = findSlashDotSlash(path.data(), path.size(), 0); | |
+ if (firstSlash != notFound) | |
+ cleanSlashDotSlashes(path, firstSlash); | |
+} | |
static inline bool matchLetter(UChar c, UChar lowercaseLetter) | |
{ | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/platform/graphics/Font.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/platform/graphics/Font.h | |
index 175cd07..ca504b1 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/platform/graphics/Font.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/platform/graphics/Font.h | |
@@ -107,6 +107,7 @@ public: | |
bool isPlatformFont() const { return m_isPlatformFont; } | |
// Metrics that we query the FontFallbackList for. | |
+#if !PLATFORM(WKC) | |
int ascent() const { return primaryFont()->ascent(); } | |
int descent() const { return primaryFont()->descent(); } | |
int height() const { return ascent() + descent(); } | |
@@ -115,6 +116,16 @@ public: | |
float xHeight() const { return primaryFont()->xHeight(); } | |
unsigned unitsPerEm() const { return primaryFont()->unitsPerEm(); } | |
int spaceWidth() const { return (int)ceilf(primaryFont()->adjustedSpaceWidth() + m_letterSpacing); } | |
+#else | |
+ int ascent() const { return m_fontList ? primaryFont()->ascent() : 0; } | |
+ int descent() const { return m_fontList ? primaryFont()->descent() : 0; } | |
+ int height() const { return ascent() + descent(); } | |
+ int lineSpacing() const { return m_fontList ? primaryFont()->lineSpacing() : 0; } | |
+ int lineGap() const { return m_fontList ? primaryFont()->lineGap() : 0; } | |
+ float xHeight() const { return m_fontList ? primaryFont()->xHeight() : 0; } | |
+ unsigned unitsPerEm() const { return m_fontList ? primaryFont()->unitsPerEm() : 0; } | |
+ int spaceWidth() const { return m_fontList ? (int)ceilf(primaryFont()->adjustedSpaceWidth() + m_letterSpacing) : 0; } | |
+#endif | |
int tabWidth() const { return 8 * spaceWidth(); } | |
const SimpleFontData* primaryFont() const; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/platform/text/BidiResolver.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/platform/text/BidiResolver.h | |
index 13e935e..c066948 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/platform/text/BidiResolver.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/platform/text/BidiResolver.h | |
@@ -361,14 +361,13 @@ void BidiResolver<Iterator, Run>::raiseExplicitEmbeddingLevel(WTF::Unicode::Dire | |
if (!emptyRun && eor != last) { | |
ASSERT(m_status.eor != OtherNeutral || eor.atEnd()); | |
// bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last | |
- ASSERT(m_status.last == EuropeanNumberSeparator | |
- || m_status.last == EuropeanNumberTerminator | |
- || m_status.last == CommonNumberSeparator | |
- || m_status.last == BoundaryNeutral | |
- || m_status.last == BlockSeparator | |
- || m_status.last == SegmentSeparator | |
- || m_status.last == WhiteSpaceNeutral | |
- || m_status.last == OtherNeutral); | |
+ ASSERT(m_status.last != NonSpacingMark | |
+ && m_status.last != BoundaryNeutral | |
+ && m_status.last != RightToLeftEmbedding | |
+ && m_status.last != LeftToRightEmbedding | |
+ && m_status.last != RightToLeftOverride | |
+ && m_status.last != LeftToRightOverride | |
+ && m_status.last != PopDirectionalFormat); | |
if (m_direction == OtherNeutral) | |
m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightToLeft; | |
if (to == LeftToRight) { | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/platform/text/StringBuffer.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/platform/text/StringBuffer.h | |
index 353a44a..aec6099 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/platform/text/StringBuffer.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/platform/text/StringBuffer.h | |
@@ -1,5 +1,5 @@ | |
/* | |
- * Copyright (C) 2008 Apple Inc. All rights reserved. | |
+ * Copyright (C) 2008, 2010 Apple Inc. All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
@@ -32,6 +32,7 @@ | |
#include <wtf/Assertions.h> | |
#include <wtf/Noncopyable.h> | |
#include <wtf/unicode/Unicode.h> | |
+#include <limits> | |
namespace WebCore { | |
@@ -39,8 +40,10 @@ class StringBuffer : public Noncopyable { | |
public: | |
explicit StringBuffer(unsigned length) | |
: m_length(length) | |
- , m_data(static_cast<UChar*>(fastMalloc(length * sizeof(UChar)))) | |
{ | |
+ if (m_length > std::numeric_limits<unsigned>::max() / sizeof(UChar)) | |
+ CRASH(); | |
+ m_data = static_cast<UChar*>(fastMalloc(m_length * sizeof(UChar))); | |
} | |
~StringBuffer() | |
{ | |
@@ -55,8 +58,11 @@ public: | |
void resize(unsigned newLength) | |
{ | |
- if (newLength > m_length) | |
+ if (newLength > m_length) { | |
+ if (newLength > std::numeric_limits<unsigned>::max() / sizeof(UChar)) | |
+ CRASH(); | |
m_data = static_cast<UChar*>(fastRealloc(m_data, newLength * sizeof(UChar))); | |
+ } | |
m_length = newLength; | |
} | |
@@ -72,6 +78,6 @@ private: | |
UChar* m_data; | |
}; | |
-} | |
+} // namespace WTF | |
-#endif | |
+#endif // StringBuffer_h | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/CounterNode.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/CounterNode.cpp | |
index 28196d6..30aecce 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/CounterNode.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/CounterNode.cpp | |
@@ -54,6 +54,11 @@ CounterNode::CounterNode(RenderObject* o, bool hasResetType, int value) | |
{ | |
} | |
+PassRefPtr<CounterNode> CounterNode::create(RenderObject* renderer, bool hasResetType, int value) | |
+{ | |
+ return adoptRef(new CounterNode(renderer, hasResetType, value)); | |
+} | |
+ | |
CounterNode* CounterNode::nextInPreOrderAfterChildren(const CounterNode* stayWithin) const | |
{ | |
if (this == stayWithin) | |
@@ -149,7 +154,10 @@ void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild, cons | |
ASSERT(!newChild->m_parent); | |
ASSERT(!newChild->m_previousSibling); | |
ASSERT(!newChild->m_nextSibling); | |
- ASSERT(!refChild || refChild->m_parent == this); | |
+ // If the refChild is not our child we can not complete the request. This hardens against bugs in RenderCounter. | |
+ // When renderers are reparented it may request that we insert counter nodes improperly. | |
+ if (refChild && refChild->m_parent != this) | |
+ return; | |
#if 1 | |
// modified at webkit.org trunk r53355 | |
if (newChild->m_hasResetType) { | |
@@ -204,32 +212,43 @@ void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild, cons | |
next->recount(identifier); | |
return; | |
} | |
+ // If the new child is the last in the sibling list we must set the parent's lastChild. | |
+ if (!newChild->m_nextSibling) | |
+ m_lastChild = newChild; | |
// The code below handles the case when a formerly root increment counter is loosing its root position | |
// and therefore its children become next siblings. | |
CounterNode* last = newChild->m_lastChild; | |
CounterNode* first = newChild->m_firstChild; | |
- newChild->m_nextSibling = first; | |
- first->m_previousSibling = newChild; | |
- // The case when the original next sibling of the inserted node becomes a child of | |
- // one of the former children of the inserted node is not handled as it is believed | |
- // to be impossible since: | |
- // 1. if the increment counter node lost it's root position as a result of another | |
- // counter node being created, it will be inserted as the last child so next is null. | |
- // 2. if the increment counter node lost it's root position as a result of a renderer being | |
- // inserted into the document's render tree, all its former children counters are attached | |
- // to children of the inserted renderer and hence cannot be in scope for counter nodes | |
- // attached to renderers that were already in the document's render tree. | |
- last->m_nextSibling = next; | |
- if (next) | |
- next->m_previousSibling = last; | |
- else | |
- m_lastChild = last; | |
- for (next = first; ; next = next->m_nextSibling) { | |
- next->m_parent = this; | |
- if (last == next) | |
- break; | |
+ if (first) { | |
+ ASSERT(last); | |
+ newChild->m_nextSibling = first; | |
+ if (m_lastChild == newChild) | |
+ m_lastChild = last; | |
+ | |
+ first->m_previousSibling = newChild; | |
+ | |
+ // The case when the original next sibling of the inserted node becomes a child of | |
+ // one of the former children of the inserted node is not handled as it is believed | |
+ // to be impossible since: | |
+ // 1. if the increment counter node lost it's root position as a result of another | |
+ // counter node being created, it will be inserted as the last child so next is null. | |
+ // 2. if the increment counter node lost it's root position as a result of a renderer being | |
+ // inserted into the document's render tree, all its former children counters are attached | |
+ // to children of the inserted renderer and hence cannot be in scope for counter nodes | |
+ // attached to renderers that were already in the document's render tree. | |
+ last->m_nextSibling = next; | |
+ if (next) { | |
+ ASSERT(next->m_previousSibling == newChild); | |
+ next->m_previousSibling = last; | |
+ } else | |
+ m_lastChild = last; | |
+ for (next = first; ; next = next->m_nextSibling) { | |
+ next->m_parent = this; | |
+ if (last == next) | |
+ break; | |
+ } | |
} | |
newChild->m_firstChild = 0; | |
newChild->m_lastChild = 0; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/CounterNode.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/CounterNode.h | |
index 15f2eb8..c942408 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/CounterNode.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/CounterNode.h | |
@@ -22,7 +22,9 @@ | |
#ifndef CounterNode_h | |
#define CounterNode_h | |
+#include <wtf/Forward.h> | |
#include <wtf/Noncopyable.h> | |
+#include <wtf/RefCounted.h> | |
// This implements a counter tree that is used for finding parents in counters() lookup, | |
// and for propagating count changes when nodes are added or removed. | |
@@ -38,9 +40,9 @@ namespace WebCore { | |
class AtomicString; | |
class RenderObject; | |
-class CounterNode : public Noncopyable { | |
+class CounterNode : public RefCounted<CounterNode> { | |
public: | |
- CounterNode(RenderObject*, bool isReset, int value); | |
+ static PassRefPtr<CounterNode> create(RenderObject*, bool isReset, int value); | |
bool actsAsReset() const { return m_hasResetType || !m_parent; } | |
bool hasResetType() const { return m_hasResetType; } | |
@@ -64,6 +66,7 @@ public: | |
void removeChild(CounterNode*, const AtomicString& identifier); | |
private: | |
+ CounterNode(RenderObject*, bool isReset, int value); | |
int computeCountInParent() const; | |
void recount(const AtomicString& identifier); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/InlineBox.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/InlineBox.cpp | |
index 3b44271..118dfb8 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/InlineBox.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/InlineBox.cpp | |
@@ -72,7 +72,8 @@ void InlineBox::destroy(RenderArena* renderArena) | |
// Recover the size left there for us by operator delete and free the memory. | |
#if defined(ENABLE_REPLACEMENT_FASTMALLOC) || defined(_CRTDBG_MAP_ALLOC) | |
- renderArena->renderarena_free(*(size_t *)this, this); | |
+ if (renderArena) | |
+ renderArena->renderarena_free(*(size_t *)this, this); | |
#else | |
renderArena->free(*(size_t *)this, this); | |
#endif | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/InlineBox.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/InlineBox.h | |
index 4b2cce8..7fba416 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/InlineBox.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/InlineBox.h | |
@@ -116,6 +116,8 @@ public: | |
virtual void paint(RenderObject::PaintInfo&, int tx, int ty); | |
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty); | |
+ InlineBox* next() const { return m_next; } | |
+ | |
// Overloaded new operator. | |
#if PLATFORM(WKC) && COMPILER(RVCT) | |
void* operator new(size_t, RenderArena*); | |
@@ -161,8 +163,6 @@ public: | |
CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); | |
#endif | |
m_constructed = true; | |
- if (m_next) | |
- m_next->setConstructed(); | |
} | |
void setExtracted(bool b = true) { m_extracted = b; } | |
@@ -297,7 +297,7 @@ protected: | |
mutable bool m_determinedIfPrevOnLineExists : 1; | |
mutable bool m_nextOnLineExists : 1; | |
mutable bool m_prevOnLineExists : 1; | |
- int m_toAdd : 12; // for justified text | |
+ signed m_toAdd : 12; // for justified text | |
#ifndef NDEBUG | |
private: | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/InlineFlowBox.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/InlineFlowBox.h | |
index 23b5cc9..669d8bb 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/InlineFlowBox.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/InlineFlowBox.h | |
@@ -68,8 +68,8 @@ public: | |
virtual void setConstructed() | |
{ | |
InlineBox::setConstructed(); | |
- if (firstChild()) | |
- firstChild()->setConstructed(); | |
+ for (InlineBox* child = firstChild(); child; child = child->next()) | |
+ child->setConstructed(); | |
} | |
void addToLine(InlineBox* child); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderBlock.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderBlock.cpp | |
index d05a412..9ce54ba 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderBlock.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderBlock.cpp | |
@@ -129,6 +129,7 @@ RenderBlock::RenderBlock(Node* node) | |
, m_inlineContinuation(0) | |
, m_maxMargin(0) | |
, m_lineHeight(-1) | |
+ , m_beingDestroyed(false) | |
{ | |
setChildrenInline(true); | |
} | |
@@ -164,6 +165,9 @@ RenderBlock::~RenderBlock() | |
void RenderBlock::destroy() | |
{ | |
+ // Mark as being destroyed to avoid trouble with merges in removeChild(). | |
+ m_beingDestroyed = true; | |
+ | |
// Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will | |
// properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise. | |
children()->destroyLeftoverChildren(); | |
@@ -267,8 +271,13 @@ void RenderBlock::updateBeforeAfterContent(PseudoId pseudoId) | |
void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild) | |
{ | |
// Make sure we don't append things after :after-generated content if we have it. | |
- if (!beforeChild && isAfterContent(lastChild())) | |
- beforeChild = lastChild(); | |
+ if (!beforeChild) { | |
+ RenderObject* lastRenderer = lastChild(); | |
+ while (lastRenderer && lastRenderer->isAnonymous() && !isAfterContent(lastRenderer)) | |
+ lastRenderer = lastRenderer->lastChild(); | |
+ if (lastRenderer && isAfterContent(lastRenderer)) | |
+ beforeChild = lastRenderer; | |
+ } | |
bool madeBoxesNonInline = false; | |
@@ -552,6 +561,10 @@ void RenderBlock::removeChild(RenderObject* oldChild) | |
&& !(prev && prev->firstChild() && prev->firstChild()->isInline() && prev->firstChild()->isRunIn()) | |
#endif | |
; | |
+ if (canDeleteAnonymousBlocks) { | |
+ canDeleteAnonymousBlocks = !(((prev && (!prev->isAnonymousBlock() || toRenderBlock(prev)->inlineContinuation() || toRenderBlock(prev)->beingDestroyed())) | |
+ || (next && (!next->isAnonymousBlock() || toRenderBlock(next)->inlineContinuation() || toRenderBlock(next)->beingDestroyed())))); | |
+ } | |
if (canDeleteAnonymousBlocks && prev && next) { | |
// Take all the children out of the |next| block and put them in | |
// the |prev| block. | |
@@ -1049,7 +1062,8 @@ bool RenderBlock::handleRunInChild(RenderBox* child) | |
if (runInNode) | |
runInNode->setRenderer(inlineRunIn); | |
- // Destroy the block run-in. | |
+ // Destroy the block run-in, which includes deleting its line box tree. | |
+ blockRunIn->deleteLineBoxTree(); | |
blockRunIn->destroy(); | |
// The block acts like an inline, so just null out its | |
@@ -4845,9 +4859,8 @@ void RenderBlock::updateFirstLetter() | |
if (remainingText->node()) | |
remainingText->node()->setRenderer(remainingText); | |
- RenderObject* nextObj = textObj->nextSibling(); | |
+ firstLetterContainer->addChild(remainingText, textObj); | |
firstLetterContainer->removeChild(textObj); | |
- firstLetterContainer->addChild(remainingText, nextObj); | |
remainingText->setFirstLetter(firstLetter); | |
#else | |
if (currChild->isText() && !currChild->isBR() && currChild->parent()->style()->styleType() != FIRST_LETTER) { | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderBlock.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderBlock.h | |
index 9b00dee..7523e9c 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderBlock.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderBlock.h | |
@@ -64,6 +64,7 @@ public: | |
RenderObjectChildList* children() { return &m_children; } | |
virtual void destroy(); | |
+ bool beingDestroyed() const { return m_beingDestroyed; } | |
// These two functions are overridden for inline-block. | |
virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const; | |
@@ -157,7 +158,7 @@ protected: | |
void moveChildTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* beforeChild, RenderObject* child); | |
#if 1 | |
// added at webkit.org trunk r53525 | |
- void moveAllChildrenTo(RenderObject* to, RenderObjectChildList* toChildList); | |
+ void moveAllChildrenTo(RenderObject* to, RenderObjectChildList* toChildList); | |
void moveAllChildrenTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* beforeChild); | |
#endif | |
@@ -263,12 +264,12 @@ private: | |
}; | |
// The following functions' implementations are in RenderBlockLineLayout.cpp. | |
+ void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat); | |
void bidiReorderLine(InlineBidiResolver&, const InlineIterator& end, bool previousLineBrokeCleanly); | |
RootInlineBox* determineStartPosition(bool& firstLine, bool& fullLayout, bool& previousLineBrokeCleanly, | |
InlineBidiResolver&, Vector<FloatWithRect>& floats, unsigned& numCleanFloats); | |
- RootInlineBox* determineEndPosition(RootInlineBox* startBox, InlineIterator& cleanLineStart, | |
- BidiStatus& cleanLineBidiStatus, | |
- int& yPos); | |
+ RootInlineBox* determineEndPosition(RootInlineBox* startBox, Vector<FloatWithRect>& floats, size_t floatIndex, InlineIterator& cleanLineStart, | |
+ BidiStatus& cleanLineBidiStatus, int& yPos); | |
bool matchedEndLine(const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus, | |
RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop); | |
@@ -533,12 +534,13 @@ private: | |
RenderObjectChildList m_children; | |
RenderLineBoxList m_lineBoxes; // All of the root line boxes created for this block flow. For example, <div>Hello<br>world.</div> will have two total lines for the <div>. | |
- mutable int m_lineHeight; | |
+ mutable signed m_lineHeight : 31; | |
+ bool m_beingDestroyed : 1; | |
#if 1 | |
// added at webkit.org trunk r53525 | |
- // RenderRubyBase objects need to be able to split and merge, moving their children around | |
- // (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline). | |
+ // RenderRubyBase objects need to be able to split and merge, moving their children around | |
+ // (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline). | |
friend class RenderRubyBase; | |
#endif | |
}; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderBlockLineLayout.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderBlockLineLayout.cpp | |
index d7013ba..419510a 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderBlockLineLayout.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderBlockLineLayout.cpp | |
@@ -1035,9 +1035,9 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i | |
// if we determine that we're able to synchronize after handling all our dirty lines. | |
InlineIterator cleanLineStart; | |
BidiStatus cleanLineBidiStatus; | |
- int endLineYPos = 0; | |
+ int endLineLogicalTop = 0; | |
RootInlineBox* endLine = (fullLayout || !startLine) ? | |
- 0 : determineEndPosition(startLine, cleanLineStart, cleanLineBidiStatus, endLineYPos); | |
+ 0 : determineEndPosition(startLine, floats, floatIndex, cleanLineStart, cleanLineBidiStatus, endLineLogicalTop); | |
if (startLine) { | |
useRepaintBounds = true; | |
@@ -1081,7 +1081,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i | |
while (!end.atEnd()) { | |
// FIXME: Is this check necessary before the first iteration or can it be moved to the end? | |
- if (checkForEndLineMatch && (endLineMatched = matchedEndLine(resolver, cleanLineStart, cleanLineBidiStatus, endLine, endLineYPos, repaintBottom, repaintTop))) | |
+ if (checkForEndLineMatch && (endLineMatched = matchedEndLine(resolver, cleanLineStart, cleanLineBidiStatus, endLine, endLineLogicalTop, repaintBottom, repaintTop))) | |
break; | |
lineMidpointState.reset(); | |
@@ -1097,7 +1097,10 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i | |
} | |
ASSERT(end != resolver.position()); | |
- if (!isLineEmpty) { | |
+ if (isLineEmpty) { | |
+ if (lastRootBox()) | |
+ lastRootBox()->setLineBreakInfo(end.obj, end.pos, resolver.status()); | |
+ } else { | |
bidiReorderLine(resolver, end, previousLineBrokeCleanly); | |
ASSERT(resolver.position() == end); | |
@@ -1219,7 +1222,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i | |
if (endLine) { | |
if (endLineMatched) { | |
// Attach all the remaining lines, and then adjust their y-positions as needed. | |
- int delta = height() - endLineYPos; | |
+ int delta = height() - endLineLogicalTop; | |
for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) { | |
line->attachLine(); | |
if (delta) { | |
@@ -1292,6 +1295,34 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i | |
checkLinesForTextOverflow(); | |
} | |
+void RenderBlock::checkFloatsInCleanLine(RootInlineBox* line, Vector<FloatWithRect>& floats, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat) | |
+{ | |
+ Vector<RenderBox*>* cleanLineFloats = line->floatsPtr(); | |
+ if (!cleanLineFloats) | |
+ return; | |
+ | |
+ Vector<RenderBox*>::iterator end = cleanLineFloats->end(); | |
+ for (Vector<RenderBox*>::iterator it = cleanLineFloats->begin(); it != end; ++it) { | |
+ RenderBox* floatingBox = *it; | |
+ floatingBox->layoutIfNeeded(); | |
+ IntSize newSize(floatingBox->width() + floatingBox->marginLeft() + floatingBox->marginRight(), floatingBox->height() + floatingBox->marginTop() + floatingBox->marginBottom()); | |
+ ASSERT(floatIndex < floats.size()); | |
+ if (floats[floatIndex].object != floatingBox) { | |
+ encounteredNewFloat = true; | |
+ return; | |
+ } | |
+ if (floats[floatIndex].rect.size() != newSize) { | |
+ int floatTop = floats[floatIndex].rect.y(); | |
+ int floatHeight = max(floats[floatIndex].rect.height(), newSize.height()); | |
+ line->markDirty(); | |
+ markLinesDirtyInVerticalRange(line->blockHeight(), floatTop + floatHeight); | |
+ floats[floatIndex].rect.setSize(newSize); | |
+ dirtiedByFloat = true; | |
+ } | |
+ floatIndex++; | |
+ } | |
+} | |
+ | |
RootInlineBox* RenderBlock::determineStartPosition(bool& firstLine, bool& fullLayout, bool& previousLineBrokeCleanly, | |
InlineBidiResolver& resolver, Vector<FloatWithRect>& floats, unsigned& numCleanFloats) | |
{ | |
@@ -1302,28 +1333,8 @@ RootInlineBox* RenderBlock::determineStartPosition(bool& firstLine, bool& fullLa | |
if (!fullLayout) { | |
size_t floatIndex = 0; | |
for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()) { | |
- if (Vector<RenderBox*>* cleanLineFloats = curr->floatsPtr()) { | |
- Vector<RenderBox*>::iterator end = cleanLineFloats->end(); | |
- for (Vector<RenderBox*>::iterator o = cleanLineFloats->begin(); o != end; ++o) { | |
- RenderBox* f = *o; | |
- IntSize newSize(f->width() + f->marginLeft() +f->marginRight(), f->height() + f->marginTop() + f->marginBottom()); | |
- ASSERT(floatIndex < floats.size()); | |
- if (floats[floatIndex].object != f) { | |
- // A new float has been inserted before this line or before its last known float. | |
- // Just do a full layout. | |
- fullLayout = true; | |
- break; | |
- } | |
- if (floats[floatIndex].rect.size() != newSize) { | |
- int floatTop = floats[floatIndex].rect.y(); | |
- curr->markDirty(); | |
- markLinesDirtyInVerticalRange(curr->blockHeight(), floatTop + max(floats[floatIndex].rect.height(), newSize.height())); | |
- floats[floatIndex].rect.setSize(newSize); | |
- dirtiedByFloat = true; | |
- } | |
- floatIndex++; | |
- } | |
- } | |
+ // If a new float has been inserted before this line or before its last known float,just do a full layout. | |
+ checkFloatsInCleanLine(curr, floats, floatIndex, fullLayout, dirtiedByFloat); | |
if (dirtiedByFloat || fullLayout) | |
break; | |
} | |
@@ -1349,7 +1360,7 @@ RootInlineBox* RenderBlock::determineStartPosition(bool& firstLine, bool& fullLa | |
// We have a dirty line. | |
if (RootInlineBox* prevRootBox = curr->prevRootBox()) { | |
// We have a previous line. | |
- if (!dirtiedByFloat && (!prevRootBox->endsWithBreak() || (prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= toRenderText(prevRootBox->lineBreakObj())->textLength()))) | |
+ if (!dirtiedByFloat && (!prevRootBox->endsWithBreak() || !prevRootBox->lineBreakObj() || (prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= toRenderText(prevRootBox->lineBreakObj())->textLength()))) | |
// The previous line didn't break cleanly or broke at a newline | |
// that has been deleted, so treat it as dirty too. | |
curr = prevRootBox; | |
@@ -1417,27 +1428,33 @@ RootInlineBox* RenderBlock::determineStartPosition(bool& firstLine, bool& fullLa | |
return curr; | |
} | |
-RootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus, int& yPos) | |
+RootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, Vector<FloatWithRect>& floats, size_t floatIndex, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus, int& logicalTop) | |
{ | |
RootInlineBox* last = 0; | |
- if (!startLine) | |
- last = 0; | |
- else { | |
- for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->nextRootBox()) { | |
- if (curr->isDirty()) | |
- last = 0; | |
- else if (!last) | |
- last = curr; | |
+ for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->nextRootBox()) { | |
+ if (!curr->isDirty()) { | |
+ bool encounteredNewFloat = false; | |
+ bool dirtiedByFloat = false; | |
+ checkFloatsInCleanLine(curr, floats, floatIndex, encounteredNewFloat, dirtiedByFloat); | |
+ if (encounteredNewFloat) | |
+ return 0; | |
} | |
+ if (curr->isDirty()) | |
+ last = 0; | |
+ else if (!last) | |
+ last = curr; | |
} | |
if (!last) | |
return 0; | |
+ // At this point, |last| is the first line in a run of clean lines that ends with the last line | |
+ // in the block. | |
+ | |
RootInlineBox* prev = last->prevRootBox(); | |
cleanLineStart = InlineIterator(this, prev->lineBreakObj(), prev->lineBreakPos()); | |
cleanLineBidiStatus = prev->lineBreakBidiStatus(); | |
- yPos = prev->blockHeight(); | |
+ logicalTop = prev->blockHeight(); | |
for (RootInlineBox* line = last; line; line = line->nextRootBox()) | |
line->extractLine(); // Disconnect all line boxes from their render objects while preserving | |
@@ -1819,6 +1836,10 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool | |
if (floatsFitOnLine && floatBox->width() + floatBox->marginLeft() + floatBox->marginRight() + w + tmpW <= width) { | |
positionNewFloats(); | |
width = lineWidth(height(), firstLine); | |
+ if (lBreak.obj == o) { | |
+ ASSERT(!lBreak.pos); | |
+ lBreak.increment(); | |
+ } | |
} else | |
floatsFitOnLine = false; | |
} else if (o->isPositioned()) { | |
@@ -2075,7 +2096,9 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool | |
lBreak.increment(); | |
previousLineBrokeCleanly = true; | |
} | |
- goto end; // Didn't fit. Jump to the end. | |
+ // Didn't fit. Jump to the end unless there's still an opportunity to collapse whitespace. | |
+ if (ignoringSpaces || !o->style()->collapseWhiteSpace() || !currentCharacterIsSpace || !previousCharacterIsSpace) | |
+ goto end; | |
} else { | |
if (!betweenWords || (midWordBreak && !autoWrap)) | |
tmpW -= additionalTmpW; | |
@@ -2183,17 +2206,17 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool | |
checkForBreak = true; | |
else if (next && o->isText() && next->isText() && !next->isBR()) { | |
if (autoWrap || (next->style()->autoWrap())) { | |
- if (currentCharacterIsSpace) | |
+ if (autoWrap && currentCharacterIsSpace) | |
checkForBreak = true; | |
else { | |
checkForBreak = false; | |
RenderText* nextText = toRenderText(next); | |
if (nextText->textLength()) { | |
UChar c = nextText->characters()[0]; | |
- if (c == ' ' || c == '\t' || (c == '\n' && !shouldPreserveNewline(next))) | |
+ if (!currentCharacterIsSpace && (c == ' ' || c == '\t' || (c == '\n' && !shouldPreserveNewline(next)))) | |
// If the next item on the line is text, and if we did not end with | |
// a space, then the next text run continues our word (and so it needs to | |
- // keep adding to |tmpW|. Just update and continue. | |
+ // keep adding to the uncommitted width. Just update and continue. | |
checkForBreak = true; | |
} else if (nextText->isWordBreak()) | |
checkForBreak = true; | |
@@ -2264,16 +2287,10 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool | |
end: | |
if (lBreak == resolver.position() && (!lBreak.obj || !lBreak.obj->isBR())) { | |
// we just add as much as possible | |
- if (style()->whiteSpace() == PRE) { | |
- // FIXME: Don't really understand this case. | |
- if (pos != 0) { | |
- lBreak.obj = o; | |
- lBreak.pos = pos - 1; | |
- } else { | |
- lBreak.obj = last; | |
- lBreak.pos = last->isText() ? last->length() : 0; | |
- lBreak.nextBreakablePosition = -1; | |
- } | |
+ if (style()->whiteSpace() == PRE && !pos) { | |
+ lBreak.obj = last; | |
+ lBreak.pos = last->isText() ? last->length() : 0; | |
+ lBreak.nextBreakablePosition = -1; | |
} else if (lBreak.obj) { | |
if (last != o && !last->isListMarker()) { | |
// better to break between object boundaries than in the middle of a word (except for list markers) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderBox.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderBox.cpp | |
index d03403e..068ef22 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderBox.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderBox.cpp | |
@@ -730,9 +730,10 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, int tx, int ty, int | |
if (!compositedMask) { | |
StyleImage* maskBoxImage = style()->maskBoxImage().image(); | |
- if (maskBoxImage && style()->maskLayers()->hasImage()) { | |
+ bool hasMaskLayerWithImage = style()->maskLayers()->hasImage(); | |
+ if (maskBoxImage && hasMaskLayerWithImage) { | |
pushTransparencyLayer = true; | |
- } else { | |
+ } else if (hasMaskLayerWithImage) { | |
// We have to use an extra image buffer to hold the mask. Multiple mask images need | |
// to composite together using source-over so that they can then combine into a single unified mask that | |
// can be composited with the content using destination-in. SVG images need to be able to set compositing modes | |
@@ -741,7 +742,7 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, int tx, int ty, int | |
// We have to check that the mask images to be rendered contain at least one image that can be actually used in rendering | |
// before pushing the transparency layer. | |
for (const FillLayer* fillLayer = style()->maskLayers()->next(); fillLayer; fillLayer = fillLayer->next()) { | |
- if (fillLayer->hasImage() && fillLayer->image()->canRender(style()->effectiveZoom())) { | |
+ if (fillLayer->image() && fillLayer->image()->canRender(style()->effectiveZoom())) { | |
pushTransparencyLayer = true; | |
// We found one image that can be used in rendering, exit the loop | |
break; | |
@@ -1615,7 +1616,7 @@ void RenderBox::calcHeight() | |
// height since we don't set a height in RenderView when we're printing. So without this quirk, the | |
// height has nothing to be a percentage of, and it ends up being 0. That is bad. | |
bool printingNeedsBaseHeight = document()->printing() && h.isPercent() | |
- && (isRoot() || (isBody() && document()->documentElement()->renderer()->style()->height().isPercent())); | |
+ && (isRoot() || (isBody() && document()->documentElement()->renderer()->style()->height().isPercent())) && !isInline(); | |
if (stretchesToViewHeight() || printingNeedsBaseHeight) { | |
int margins = collapsedMarginTop() + collapsedMarginBottom(); | |
int visHeight = document()->printing() ? view()->frameView()->visibleHeight() : view()->viewHeight(); | |
@@ -2939,7 +2940,7 @@ bool RenderBox::shrinkToAvoidFloats() const | |
bool RenderBox::avoidsFloats() const | |
{ | |
- return isReplaced() || hasOverflowClip() || isHR(); | |
+ return isReplaced() || hasOverflowClip() || isHR() || isDeprecatedFlexItem(); | |
} | |
void RenderBox::addShadowOverflow() | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderBox.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderBox.h | |
index 5ed271a..f3af681 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderBox.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderBox.h | |
@@ -217,7 +217,7 @@ public: | |
bool stretchesToViewHeight() const | |
{ | |
- return style()->htmlHacks() && style()->height().isAuto() && !isFloatingOrPositioned() && (isRoot() || isBody()); | |
+ return style()->htmlHacks() && style()->height().isAuto() && !isFloatingOrPositioned() && (isRoot() || isBody()) && !isInline(); | |
} | |
virtual IntSize intrinsicSize() const { return IntSize(); } | |
@@ -297,6 +297,8 @@ public: | |
bool shrinkToAvoidFloats() const; | |
virtual bool avoidsFloats() const; | |
+ bool isDeprecatedFlexItem() const { return !isInline() && !isFloatingOrPositioned() && parent() && parent()->isFlexibleBox(); } | |
+ | |
#if ENABLE(SVG) | |
virtual TransformationMatrix localTransform() const; | |
#endif | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderBoxModelObject.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderBoxModelObject.cpp | |
index 2b0b857..59df760 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderBoxModelObject.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderBoxModelObject.cpp | |
@@ -527,6 +527,7 @@ IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer, | |
case SizeLength: { | |
int w = positioningAreaSize.width(); | |
int h = positioningAreaSize.height(); | |
+ | |
Length layerWidth = fillLayer->size().size.width(); | |
Length layerHeight = fillLayer->size().size.height(); | |
@@ -542,15 +543,19 @@ IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer, | |
// If one of the values is auto we have to use the appropriate | |
// scale to maintain our aspect ratio. | |
- if (layerWidth.isAuto() && !layerHeight.isAuto()) | |
- w = image->imageSize(this, style()->effectiveZoom()).width() * h / image->imageSize(this, style()->effectiveZoom()).height(); | |
- else if (!layerWidth.isAuto() && layerHeight.isAuto()) | |
- h = image->imageSize(this, style()->effectiveZoom()).height() * w / image->imageSize(this, style()->effectiveZoom()).width(); | |
- else if (layerWidth.isAuto() && layerHeight.isAuto()) { | |
- // If both width and height are auto, we just want to use the image's | |
- // intrinsic size. | |
- w = image->imageSize(this, style()->effectiveZoom()).width(); | |
- h = image->imageSize(this, style()->effectiveZoom()).height(); | |
+ if (layerWidth.isAuto() && !layerHeight.isAuto()) { | |
+ IntSize imageIntrinsicSize = image->imageSize(this, style()->effectiveZoom()); | |
+ if (imageIntrinsicSize.height()) | |
+ w = imageIntrinsicSize.width() * h / imageIntrinsicSize.height(); | |
+ } else if (!layerWidth.isAuto() && layerHeight.isAuto()) { | |
+ IntSize imageIntrinsicSize = image->imageSize(this, style()->effectiveZoom()); | |
+ if (imageIntrinsicSize.width()) | |
+ h = imageIntrinsicSize.height() * w / imageIntrinsicSize.width(); | |
+ } else if (layerWidth.isAuto() && layerHeight.isAuto()) { | |
+ // If both width and height are auto, use the image's intrinsic size. | |
+ IntSize imageIntrinsicSize = image->imageSize(this, style()->effectiveZoom()); | |
+ w = imageIntrinsicSize.width(); | |
+ h = imageIntrinsicSize.height(); | |
} | |
return IntSize(max(1, w), max(1, h)); | |
@@ -558,8 +563,10 @@ IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer, | |
case Contain: | |
case Cover: { | |
IntSize imageIntrinsicSize = image->imageSize(this, 1); | |
- float horizontalScaleFactor = static_cast<float>(positioningAreaSize.width()) / imageIntrinsicSize.width(); | |
- float verticalScaleFactor = static_cast<float>(positioningAreaSize.height()) / imageIntrinsicSize.height(); | |
+ float horizontalScaleFactor = imageIntrinsicSize.width() | |
+ ? static_cast<float>(positioningAreaSize.width()) / imageIntrinsicSize.width() : 1; | |
+ float verticalScaleFactor = imageIntrinsicSize.height() | |
+ ? static_cast<float>(positioningAreaSize.height()) / imageIntrinsicSize.height() : 1; | |
float scaleFactor = type == Contain ? min(horizontalScaleFactor, verticalScaleFactor) : max(horizontalScaleFactor, verticalScaleFactor); | |
return IntSize(max<int>(1, imageIntrinsicSize.width() * scaleFactor), max<int>(1, imageIntrinsicSize.height() * scaleFactor)); | |
@@ -567,6 +574,7 @@ IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer, | |
case SizeNone: | |
break; | |
} | |
+ | |
return image->imageSize(this, style()->effectiveZoom()); | |
} | |
@@ -815,6 +823,11 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, | |
#if PLATFORM(WKC) | |
CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); | |
#endif | |
+ if (graphicsContext->paintingDisabled()) | |
+ return; | |
+ if (w<=0 || h<=0) | |
+ return; | |
+ | |
if (paintNinePieceImage(graphicsContext, tx, ty, w, h, style, style->borderImage())) | |
return; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderCounter.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderCounter.cpp | |
index fb9ba9d..d05e65b 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderCounter.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderCounter.cpp | |
@@ -36,7 +36,7 @@ namespace WebCore { | |
using namespace HTMLNames; | |
-typedef HashMap<RefPtr<AtomicStringImpl>, CounterNode*> CounterMap; | |
+typedef HashMap<RefPtr<AtomicStringImpl>, RefPtr<CounterNode> > CounterMap; | |
typedef HashMap<const RenderObject*, CounterMap*> CounterMaps; | |
static CounterNode* makeCounterNode(RenderObject*, const AtomicString& identifier, bool alwaysCreateCounter); | |
@@ -149,7 +149,7 @@ static bool planCounter(RenderObject* object, const AtomicString& identifier, bo | |
// reset node. | |
// - Non-reset CounterNodes cannot have descendants. | |
-static bool findPlaceForCounter(RenderObject* counterOwner, const AtomicString& identifier, bool isReset, CounterNode*& parent, CounterNode*& previousSibling) | |
+static bool findPlaceForCounter(RenderObject* counterOwner, const AtomicString& identifier, bool isReset, RefPtr<CounterNode>& parent, RefPtr<CounterNode>& previousSibling) | |
{ | |
// We cannot stop searching for counters with the same identifier before we also | |
// check this renderer, because it may affect the positioning in the tree of our counter. | |
@@ -179,14 +179,20 @@ static bool findPlaceForCounter(RenderObject* counterOwner, const AtomicString& | |
// We are not a reset node or the previous reset must be on an ancestor of our renderer | |
// hence we must be a child of that reset counter. | |
parent = currentCounter; | |
- ASSERT(previousSibling->parent() == currentCounter); | |
+ // In some cases renders can be reparented (ex. nodes inside a table but not in a column or row). | |
+ // In these cases the identified previousSibling will be invalid as its parent is different from | |
+ // our identified parent. | |
+ if (previousSibling->parent() != currentCounter) | |
+ previousSibling = 0; | |
return true; | |
} | |
// CurrentCounter, the counter at the EndSearchRenderer, is not reset. | |
if (!isReset || currentRenderer->parent() != counterOwner->parent()) { | |
// If the node we are placing is not reset or we have found a counter that is attached | |
// to an ancestor of the placed counter's renderer we know we are a sibling of that node. | |
- ASSERT(currentCounter->parent() == previousSibling->parent()); | |
+ if (currentCounter->parent() != previousSibling->parent()) | |
+ return false; | |
+ | |
parent = currentCounter->parent(); | |
return true; | |
} | |
@@ -254,21 +260,23 @@ static CounterNode* makeCounterNode(RenderObject* object, const AtomicString& id | |
{ | |
ASSERT(object); | |
- if (object->m_hasCounterNodeMap) | |
- if (CounterMap* nodeMap = counterMaps().get(object)) | |
- if (CounterNode* node = nodeMap->get(identifier.impl())) | |
+ if (object->m_hasCounterNodeMap) { | |
+ if (CounterMap* nodeMap = counterMaps().get(object)) { | |
+ if (CounterNode* node = nodeMap->get(identifier.impl()).get()) | |
return node; | |
+ } | |
+ } | |
bool isReset = false; | |
int value = 0; | |
if (!planCounter(object, identifier, isReset, value) && !alwaysCreateCounter) | |
return 0; | |
- CounterNode* newParent = 0; | |
- CounterNode* newPreviousSibling = 0; | |
- CounterNode* newNode = new CounterNode(object, isReset, value); | |
+ RefPtr<CounterNode> newParent = 0; | |
+ RefPtr<CounterNode> newPreviousSibling = 0; | |
+ RefPtr<CounterNode> newNode = CounterNode::create(object, isReset, value); | |
if (findPlaceForCounter(object, identifier, isReset, newParent, newPreviousSibling)) | |
- newParent->insertAfter(newNode, newPreviousSibling, identifier); | |
+ newParent->insertAfter(newNode.get(), newPreviousSibling.get(), identifier); | |
CounterMap* nodeMap; | |
if (object->m_hasCounterNodeMap) | |
nodeMap = counterMaps().get(object); | |
@@ -281,7 +289,7 @@ static CounterNode* makeCounterNode(RenderObject* object, const AtomicString& id | |
#if 1 | |
// modified at webkit.org trunk r53355 | |
if (newNode->parent() || !object->nextInPreOrder(object->parent())) | |
- return newNode; | |
+ return newNode.get(); | |
// Checking if some nodes that were previously counter tree root nodes | |
// should become children of this node now. | |
CounterMaps& maps = counterMaps(); | |
@@ -289,11 +297,10 @@ static CounterNode* makeCounterNode(RenderObject* object, const AtomicString& id | |
for (RenderObject* currentRenderer = object->nextInPreOrder(stayWithin); currentRenderer; currentRenderer = currentRenderer->nextInPreOrder(stayWithin)) { | |
if (!currentRenderer->m_hasCounterNodeMap) | |
continue; | |
- CounterNode* currentCounter = maps.get(currentRenderer)->get(identifier.impl()); | |
+ CounterNode* currentCounter = maps.get(currentRenderer)->get(identifier.impl()).get(); | |
if (!currentCounter) | |
continue; | |
if (currentCounter->parent()) { | |
- ASSERT(newNode->firstChild()); | |
if (currentRenderer->lastChild()) | |
currentRenderer = currentRenderer->lastChild(); | |
continue; | |
@@ -304,7 +311,7 @@ static CounterNode* makeCounterNode(RenderObject* object, const AtomicString& id | |
currentRenderer = currentRenderer->lastChild(); | |
} | |
#endif | |
- return newNode; | |
+ return newNode.get(); | |
} | |
RenderCounter::RenderCounter(Document* node, const CounterContent& counter) | |
@@ -371,9 +378,9 @@ static void destroyCounterNodeChildren(const AtomicString& identifier, CounterNo | |
#endif | |
{ | |
CounterNode* previous; | |
- for (CounterNode* child = node->lastDescendant(); child && child != node; child = previous) { | |
+ for (RefPtr<CounterNode> child = node->lastDescendant(); child && child != node; child = previous) { | |
previous = child->previousInPreOrder(); | |
- child->parent()->removeChild(child, identifier); | |
+ child->parent()->removeChild(child.get(), identifier); | |
ASSERT(counterMaps().get(child->renderer())->get(identifier.impl()) == child); | |
counterMaps().get(child->renderer())->remove(identifier.impl()); | |
if (!child->renderer()->documentBeingDestroyed()) { | |
@@ -381,7 +388,6 @@ static void destroyCounterNodeChildren(const AtomicString& identifier, CounterNo | |
if (children) | |
children->invalidateCounters(child->renderer(), identifier); | |
} | |
- delete child; | |
} | |
#if 1 | |
// modified at webkit.org trunk r53355 | |
@@ -392,7 +398,6 @@ static void destroyCounterNodeChildren(const AtomicString& identifier, CounterNo | |
} | |
if (CounterNode* parent = node->parent()) | |
parent->removeChild(node, identifier); | |
- delete node; | |
} | |
void RenderCounter::destroyCounterNodes(RenderObject* renderer) | |
@@ -433,7 +438,7 @@ void RenderCounter::destroyCounterNodes(RenderObject* object) | |
#endif | |
#if 1 | |
// modified at webkit.org trunk r53355 | |
- destroyCounterNodeWithoutMapRemoval(identifier, it->second); | |
+ destroyCounterNodeWithoutMapRemoval(identifier, it->second.get()); | |
} | |
maps.remove(mapsIterator); | |
#endif | |
@@ -454,7 +459,7 @@ void RenderCounter::destroyCounterNode(RenderObject* renderer, const AtomicStrin | |
CounterMap::iterator mapIterator = map->find(identifier.impl()); | |
if (mapIterator == map->end()) | |
return; | |
- destroyCounterNodeWithoutMapRemoval(identifier, mapIterator->second); | |
+ destroyCounterNodeWithoutMapRemoval(identifier, mapIterator->second.get()); | |
map->remove(mapIterator); | |
// We do not delete "map" here even if empty because we expect to reuse | |
// it soon. In order for a renderer to lose all its counters permanently, | |
@@ -484,23 +489,26 @@ static void updateCounters(RenderObject* renderer) | |
CounterMap* counterMap = counterMaps().get(renderer); | |
ASSERT(counterMap); | |
for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != end; ++it) { | |
- CounterNode* node = counterMap->get(it->first.get()); | |
+ RefPtr<CounterNode> node = counterMap->get(it->first.get()); | |
if (!node) { | |
makeCounterNode(renderer, AtomicString(it->first.get()), false); | |
continue; | |
} | |
- CounterNode* newParent = 0; | |
- CounterNode* newPreviousSibling; | |
+ RefPtr<CounterNode> newParent = 0; | |
+ RefPtr<CounterNode> newPreviousSibling; | |
+ | |
findPlaceForCounter(renderer, AtomicString(it->first.get()), node->hasResetType(), newParent, newPreviousSibling); | |
+ if (node != counterMap->get(it->first.get())) | |
+ continue; | |
CounterNode* parent = node->parent(); | |
if (newParent == parent && newPreviousSibling == node->previousSibling()) | |
continue; | |
if (parent) | |
- parent->removeChild(node, it->first.get()); | |
+ parent->removeChild(node.get(), it->first.get()); | |
#if 1 | |
// added at webkit.org trunk r54317 | |
if (newParent) | |
- newParent->insertAfter(node, newPreviousSibling, it->first.get()); | |
+ newParent->insertAfter(node.get(), newPreviousSibling.get(), it->first.get()); | |
#else | |
newParent->insertAfter(node, newPreviousSibling, it->first.get()); | |
#endif | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderFlexibleBox.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderFlexibleBox.cpp | |
index 9649b17..69a6879 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderFlexibleBox.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderFlexibleBox.cpp | |
@@ -43,19 +43,20 @@ namespace WebCore { | |
class FlexBoxIterator { | |
public: | |
FlexBoxIterator(RenderFlexibleBox* parent) | |
+ : m_box(parent) | |
+ , m_largestOrdinal(1) | |
{ | |
- box = parent; | |
- if (box->style()->boxOrient() == HORIZONTAL && box->style()->direction() == RTL) | |
- forward = box->style()->boxDirection() != BNORMAL; | |
+ if (m_box->style()->boxOrient() == HORIZONTAL && m_box->style()->direction() == RTL) | |
+ m_forward = m_box->style()->boxDirection() != BNORMAL; | |
else | |
- forward = box->style()->boxDirection() == BNORMAL; | |
- lastOrdinal = 1; | |
- if (!forward) { | |
+ m_forward = m_box->style()->boxDirection() == BNORMAL; | |
+ m_largestOrdinal = 1; | |
+ if (!m_forward) { | |
// No choice, since we're going backwards, we have to find out the highest ordinal up front. | |
- RenderBox* child = box->firstChildBox(); | |
+ RenderBox* child = m_box->firstChildBox(); | |
while (child) { | |
- if (child->style()->boxOrdinalGroup() > lastOrdinal) | |
- lastOrdinal = child->style()->boxOrdinalGroup(); | |
+ if (child->style()->boxOrdinalGroup() > m_largestOrdinal) | |
+ m_largestOrdinal = child->style()->boxOrdinalGroup(); | |
child = child->nextSiblingBox(); | |
} | |
} | |
@@ -65,8 +66,8 @@ public: | |
void reset() | |
{ | |
- current = 0; | |
- currentOrdinal = forward ? 0 : lastOrdinal+1; | |
+ m_currentChild = 0; | |
+ m_ordinalIteration = -1; | |
} | |
RenderBox* first() | |
@@ -77,35 +78,50 @@ public: | |
RenderBox* next() | |
{ | |
- do { | |
- if (!current) { | |
- if (forward) { | |
- currentOrdinal++; | |
- if (currentOrdinal > lastOrdinal) | |
- return 0; | |
- current = box->firstChildBox(); | |
- } else { | |
- currentOrdinal--; | |
- if (currentOrdinal == 0) | |
+ do { | |
+ if (!m_currentChild) { | |
+ ++m_ordinalIteration; | |
+ | |
+ if (!m_ordinalIteration) | |
+ m_currentOrdinal = m_forward ? 1 : m_largestOrdinal; | |
+ else { | |
+ if (m_ordinalIteration >= m_ordinalValues.size() + 1) | |
return 0; | |
- current = box->lastChildBox(); | |
+ | |
+ // Only copy+sort the values once per layout even if the iterator is reset. | |
+ if (static_cast<size_t>(m_ordinalValues.size()) != m_sortedOrdinalValues.size()) { | |
+ copyToVector(m_ordinalValues, m_sortedOrdinalValues); | |
+ sort(m_sortedOrdinalValues.begin(), m_sortedOrdinalValues.end()); | |
+ } | |
+ m_currentOrdinal = m_forward ? m_sortedOrdinalValues[m_ordinalIteration - 1] : m_sortedOrdinalValues[m_sortedOrdinalValues.size() - m_ordinalIteration]; | |
} | |
- } | |
- else | |
- current = forward ? current->nextSiblingBox() : current->previousSiblingBox(); | |
- if (current && current->style()->boxOrdinalGroup() > lastOrdinal) | |
- lastOrdinal = current->style()->boxOrdinalGroup(); | |
- } while (!current || current->style()->boxOrdinalGroup() != currentOrdinal || | |
- current->style()->visibility() == COLLAPSE); | |
- return current; | |
+ | |
+ m_currentChild = m_forward ? m_box->firstChildBox() : m_box->lastChildBox(); | |
+ } else | |
+ m_currentChild = m_forward ? m_currentChild->nextSiblingBox() : m_currentChild->previousSiblingBox(); | |
+ | |
+ if (m_currentChild && notFirstOrdinalValue()) | |
+ m_ordinalValues.add(m_currentChild->style()->boxOrdinalGroup()); | |
+ } while (!m_currentChild || (!m_currentChild->isAnonymous() | |
+ && (m_currentChild->style()->boxOrdinalGroup() != m_currentOrdinal || m_currentChild->style()->visibility() == COLLAPSE))); | |
+ return m_currentChild; | |
} | |
private: | |
- RenderFlexibleBox* box; | |
- RenderBox* current; | |
- bool forward; | |
- unsigned int currentOrdinal; | |
- unsigned int lastOrdinal; | |
+ bool notFirstOrdinalValue() | |
+ { | |
+ unsigned int firstOrdinalValue = m_forward ? 1 : m_largestOrdinal; | |
+ return m_currentOrdinal == firstOrdinalValue && m_currentChild->style()->boxOrdinalGroup() != firstOrdinalValue; | |
+ } | |
+ | |
+ RenderFlexibleBox* m_box; | |
+ RenderBox* m_currentChild; | |
+ bool m_forward; | |
+ unsigned int m_currentOrdinal; | |
+ unsigned int m_largestOrdinal; | |
+ HashSet<unsigned int> m_ordinalValues; | |
+ Vector<unsigned int> m_sortedOrdinalValues; | |
+ int m_ordinalIteration; | |
}; | |
RenderFlexibleBox::RenderFlexibleBox(Node* node) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderFrameSet.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderFrameSet.cpp | |
index 22fe93f..eb2d2ac 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderFrameSet.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderFrameSet.cpp | |
@@ -144,14 +144,14 @@ void RenderFrameSet::paint(PaintInfo& paintInfo, int tx, int ty) | |
tx += x(); | |
ty += y(); | |
- int rows = frameSet()->totalRows(); | |
- int cols = frameSet()->totalCols(); | |
+ size_t rows = m_rows.m_sizes.size(); | |
+ size_t cols = m_cols.m_sizes.size(); | |
int borderThickness = frameSet()->border(); | |
int yPos = 0; | |
- for (int r = 0; r < rows; r++) { | |
+ for (size_t r = 0; r < rows; r++) { | |
int xPos = 0; | |
- for (int c = 0; c < cols; c++) { | |
+ for (size_t c = 0; c < cols; c++) { | |
child->paint(paintInfo, tx, ty); | |
xPos += m_cols.m_sizes[c]; | |
if (borderThickness && m_cols.m_allowBorder[c + 1]) { | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderImage.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderImage.cpp | |
index 57dd03b..bdce452 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderImage.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderImage.cpp | |
@@ -271,6 +271,9 @@ bool RenderImage::setImageSizeForAltText(CachedImage* newImage /* = 0 */) | |
void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect) | |
{ | |
+ if (!containingBlock()) | |
+ return; | |
+ | |
if (documentBeingDestroyed()) | |
return; | |
@@ -296,7 +299,7 @@ void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect) | |
// In the case of generated image content using :before/:after, we might not be in the | |
// render tree yet. In that case, we don't need to worry about check for layout, since we'll get a | |
// layout when we get added in to the render tree hierarchy later. | |
- if (containingBlock()) { | |
+ if (!prefWidthsDirty()) { | |
// lets see if we need to relayout at all.. | |
int oldwidth = width(); | |
int oldheight = height(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderInline.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderInline.cpp | |
index 77ddd3c..609610b 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderInline.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderInline.cpp | |
@@ -1054,6 +1054,10 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, int tx, | |
int l = tx + thisline.x() - offset; | |
int b = ty + thisline.bottom() + offset; | |
int r = tx + thisline.right() + offset; | |
+ | |
+ IntRect box(l, t, b-t, r-l); | |
+ if (box.isEmpty()) | |
+ return; | |
// left edge | |
drawLineForBoxSide(graphicsContext, | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderLayer.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderLayer.cpp | |
index 3cb5adb..230d823 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderLayer.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderLayer.cpp | |
@@ -334,12 +334,12 @@ void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags) | |
#if 1 | |
// added at webkit.org trunk r61686 | |
-IntRect RenderLayer::repaintRectIncludingDescendants() const | |
-{ | |
- IntRect repaintRect = m_repaintRect; | |
- for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) | |
- repaintRect.unite(child->repaintRectIncludingDescendants()); | |
- return repaintRect; | |
+IntRect RenderLayer::repaintRectIncludingDescendants() const | |
+{ | |
+ IntRect repaintRect = m_repaintRect; | |
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) | |
+ repaintRect.unite(child->repaintRectIncludingDescendants()); | |
+ return repaintRect; | |
} | |
#endif | |
@@ -1251,7 +1251,8 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai | |
// Schedule the scroll DOM event. | |
if (view) { | |
if (FrameView* frameView = view->frameView()) | |
- frameView->scheduleEvent(Event::create(eventNames().scrollEvent, false, false), renderer()->node()); | |
+ if (renderer()->node()) | |
+ frameView->scheduleEvent(Event::create(eventNames().scrollEvent, false, false), renderer()->node()); | |
} | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderListItem.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderListItem.cpp | |
index 9734326..6d84cc2 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderListItem.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderListItem.cpp | |
@@ -1,7 +1,7 @@ | |
/** | |
* Copyright (C) 1999 Lars Knoll (knoll@kde.org) | |
* (C) 1999 Antti Koivisto (koivisto@kde.org) | |
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. | |
+ * Copyright (C) 2003, 2004, 2005, 2006, 2010 Apple Inc. All rights reserved. | |
* Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) | |
* Copyright (c) 2010,2011 ACCESS CO., LTD. All rights reserved. | |
* | |
@@ -76,11 +76,16 @@ void RenderListItem::destroy() | |
RenderBlock::destroy(); | |
} | |
+static bool isList(Node* node) | |
+{ | |
+ return (node->hasTagName(ulTag) || node->hasTagName(olTag)); | |
+} | |
+ | |
static Node* enclosingList(Node* node) | |
{ | |
Node* parent = node->parentNode(); | |
for (Node* n = parent; n; n = n->parentNode()) | |
- if (n->hasTagName(ulTag) || n->hasTagName(olTag)) | |
+ if (isList(n)) | |
return n; | |
// If there's no actual <ul> or <ol> list element, then our parent acts as | |
// our list for purposes of determining what other list items should be | |
@@ -88,22 +93,38 @@ static Node* enclosingList(Node* node) | |
return parent; | |
} | |
+static Node* enclosingList(const RenderObject* renderer) | |
+{ | |
+ Node* node = renderer->node(); | |
+ if (node) | |
+ return enclosingList(node); | |
+ | |
+ renderer = renderer->parent(); | |
+ while (renderer && !renderer->node()) | |
+ renderer = renderer->parent(); | |
+ | |
+ node = renderer->node(); | |
+ if (isList(node)) | |
+ return node; | |
+ | |
+ return enclosingList(node); | |
+} | |
+ | |
static RenderListItem* previousListItem(Node* list, const RenderListItem* item) | |
{ | |
- for (Node* node = item->node()->traversePreviousNode(); node != list; node = node->traversePreviousNode()) { | |
- RenderObject* renderer = node->renderer(); | |
- if (!renderer || !renderer->isListItem()) | |
+ for (RenderObject* renderer = item->previousInPreOrder(); renderer != list->renderer(); renderer = renderer->previousInPreOrder()) { | |
+ if (!renderer->isListItem()) | |
continue; | |
- Node* otherList = enclosingList(node); | |
+ Node* otherList = enclosingList(renderer); | |
// This item is part of our current list, so it's what we're looking for. | |
if (list == otherList) | |
return toRenderListItem(renderer); | |
// We found ourself inside another list; lets skip the rest of it. | |
- // Use traverseNextNode() here because the other list itself may actually | |
+ // Use nextInPreOrder() here because the other list itself may actually | |
// be a list item itself. We need to examine it, so we do this to counteract | |
- // the traversePreviousNode() that will be done by the loop. | |
+ // the previousInPreOrder() that will be done by the loop. | |
if (otherList) | |
- node = otherList->traverseNextNode(); | |
+ renderer = otherList->renderer()->nextInPreOrder(); | |
} | |
return 0; | |
} | |
@@ -112,7 +133,7 @@ inline int RenderListItem::calcValue() const | |
{ | |
if (m_hasExplicitValue) | |
return m_explicitValue; | |
- Node* list = enclosingList(node()); | |
+ Node* list = enclosingList(this); | |
// FIXME: This recurses to a possible depth of the length of the list. | |
// That's not good -- we need to change this to an iterative algorithm. | |
if (RenderListItem* previousItem = previousListItem(list, this)) | |
@@ -233,7 +254,7 @@ void RenderListItem::layout() | |
void RenderListItem::positionListMarker() | |
{ | |
- if (m_marker && !m_marker->isInside() && m_marker->inlineBoxWrapper()) { | |
+ if (m_marker && m_marker->parent()->isBox() && !m_marker->isInside() && m_marker->inlineBoxWrapper()) { | |
int markerOldX = m_marker->x(); | |
int yOffset = 0; | |
int xOffset = 0; | |
@@ -350,6 +371,8 @@ void RenderListItem::explicitValueChanged() | |
void RenderListItem::setExplicitValue(int value) | |
{ | |
+ ASSERT(node()); | |
+ | |
if (m_hasExplicitValue && m_explicitValue == value) | |
return; | |
m_explicitValue = value; | |
@@ -360,6 +383,8 @@ void RenderListItem::setExplicitValue(int value) | |
void RenderListItem::clearExplicitValue() | |
{ | |
+ ASSERT(node()); | |
+ | |
if (!m_hasExplicitValue) | |
return; | |
m_hasExplicitValue = false; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderListMarker.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderListMarker.cpp | |
index 0c3f83c..12f20f4 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderListMarker.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderListMarker.cpp | |
@@ -649,7 +649,6 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) | |
void RenderListMarker::layout() | |
{ | |
ASSERT(needsLayout()); | |
- ASSERT(!prefWidthsDirty()); | |
if (isImage()) { | |
setWidth(m_image->imageSize(this, style()->effectiveZoom()).width()); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderObject.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderObject.cpp | |
index 54f1500..92e37fa 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderObject.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderObject.cpp | |
@@ -2079,7 +2079,8 @@ void RenderObject::destroy() | |
document()->axObjectCache()->childrenChanged(this->parent()); | |
document()->axObjectCache()->remove(this); | |
} | |
- animation()->cancelAnimations(this); | |
+ if (document()->frame()) | |
+ animation()->cancelAnimations(this); | |
// By default no ref-counting. RenderWidget::destroy() doesn't call | |
// this function because it needs to do ref-counting. If anything | |
@@ -2127,7 +2128,8 @@ void RenderObject::arenaDelete(RenderArena* arena, void* base) | |
// Recover the size left there for us by operator delete and free the memory. | |
#if defined(ENABLE_REPLACEMENT_FASTMALLOC) || defined(_CRTDBG_MAP_ALLOC) | |
- arena->renderarena_free(*(size_t*)base, base); | |
+ if (arena) | |
+ arena->renderarena_free(*(size_t*)base, base); | |
#else | |
arena->free(*(size_t*)base, base); | |
#endif | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderObject.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderObject.h | |
index d161293..763b506 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderObject.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderObject.h | |
@@ -314,7 +314,9 @@ public: | |
bool isHTMLMarquee() const; | |
+ inline bool isBeforeContent() const; | |
inline bool isAfterContent() const; | |
+ static inline bool isBeforeContent(const RenderObject* obj) { return obj && obj->isBeforeContent(); } | |
static inline bool isAfterContent(const RenderObject* obj) { return obj && obj->isAfterContent(); } | |
bool childrenInline() const { return m_childrenInline; } | |
@@ -895,6 +897,16 @@ inline bool RenderObject::documentBeingDestroyed() const | |
return !document()->renderer(); | |
} | |
+inline bool RenderObject::isBeforeContent() const | |
+{ | |
+ if (style()->styleType() != BEFORE) | |
+ return false; | |
+ // Text nodes don't have their own styles, so ignore the style on a text node. | |
+ if (isText() && !isBR()) | |
+ return false; | |
+ return true; | |
+} | |
+ | |
inline bool RenderObject::isAfterContent() const | |
{ | |
if (style()->styleType() != AFTER) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderObjectChildList.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderObjectChildList.cpp | |
index be525c4..4fd4f29 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderObjectChildList.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderObjectChildList.cpp | |
@@ -54,10 +54,10 @@ void RenderObjectChildList::destroyLeftoverChildren() | |
firstChild()->remove(); // List markers are owned by their enclosing list and so don't get destroyed by this container. Similarly, first letters are destroyed by their remaining text fragment. | |
#if 1 | |
// modified at webkit.org trunk r63772 | |
- else if (firstChild()->isRunIn() && firstChild()->node()) { | |
- firstChild()->node()->setRenderer(0); | |
- firstChild()->node()->setNeedsStyleRecalc(); | |
- firstChild()->destroy(); | |
+ else if (firstChild()->isRunIn() && firstChild()->node()) { | |
+ firstChild()->node()->setRenderer(0); | |
+ firstChild()->node()->setNeedsStyleRecalc(); | |
+ firstChild()->destroy(); | |
} else { | |
#else | |
else { | |
@@ -372,6 +372,21 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo | |
if (!beforeAfterParent) | |
return; | |
+ // When beforeAfterParent is not equal to child (e.g. in tables), | |
+ // we need to create new styles inheriting from pseudoElementStyle | |
+ // on all the intermediate parents (leaving their display same). | |
+ if (beforeAfterParent != child) { | |
+ RenderObject* curr = beforeAfterParent; | |
+ while (curr && curr != child) { | |
+ ASSERT(curr->isAnonymous()); | |
+ RefPtr<RenderStyle> newStyle = RenderStyle::create(); | |
+ newStyle->inheritFrom(pseudoElementStyle); | |
+ newStyle->setDisplay(curr->style()->display()); | |
+ curr->setStyle(newStyle); | |
+ curr = curr->parent(); | |
+ } | |
+ } | |
+ | |
// Note that if we ever support additional types of generated content (which should be way off | |
// in the future), this code will need to be patched. | |
for (RenderObject* genChild = beforeAfterParent->firstChild(); genChild; genChild = genChild->nextSibling()) { | |
@@ -431,9 +446,18 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo | |
// to find the original content properly. | |
generatedContentContainer = RenderObject::createObject(owner->document(), pseudoElementStyle); | |
generatedContentContainer->setStyle(pseudoElementStyle); | |
+ if (!owner->isChildAllowed(generatedContentContainer, pseudoElementStyle)) { | |
+ // The generated content container is not allowed here -> abort. | |
+ generatedContentContainer->destroy(); | |
+ renderer->destroy(); | |
+ return; | |
+ } | |
owner->addChild(generatedContentContainer, insertBefore); | |
} | |
- generatedContentContainer->addChild(renderer); | |
+ if (generatedContentContainer->isChildAllowed(renderer, pseudoElementStyle)) | |
+ generatedContentContainer->addChild(renderer); | |
+ else | |
+ renderer->destroy(); | |
} | |
} | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderPartObject.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderPartObject.cpp | |
index de51d20..d260f42 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderPartObject.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderPartObject.cpp | |
@@ -281,8 +281,16 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins) | |
return; | |
} | |
- bool success = o->dispatchBeforeLoadEvent(url) && | |
- frame->loader()->requestObject(this, url, o->getAttribute(nameAttr), serviceType, paramNames, paramValues); | |
+ bool beforeLoadAllowedLoad = o->dispatchBeforeLoadEvent(url); | |
+ | |
+ // beforeload events can modify the DOM, potentially causing | |
+ // RenderWidget::destroy() to be called. Ensure we haven't been | |
+ // destroyed before continuing. | |
+ if (!node()) | |
+ return; | |
+ | |
+ bool success = beforeLoadAllowedLoad && frame->loader()->requestObject(this, url, o->getAttribute(nameAttr), serviceType, paramNames, paramValues); | |
+ | |
if (!success && m_hasFallbackContent) | |
o->renderFallbackContent(); | |
} else if (node()->hasTagName(embedTag)) { | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderRuby.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderRuby.cpp | |
index 8d113f9..c2f80be 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderRuby.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderRuby.cpp | |
@@ -32,18 +32,71 @@ | |
#include "RenderRuby.h" | |
#include "RenderRubyRun.h" | |
+#include "RenderStyle.h" | |
+#include <wtf/RefPtr.h> | |
namespace WebCore { | |
//=== generic helper functions to avoid excessive code duplication === | |
+static inline bool isAnonymousRubyInlineBlock(const RenderObject* object) | |
+{ | |
+ ASSERT(!object | |
+ || !object->parent()->isRuby() | |
+ || object->isRubyRun() | |
+ || (object->isInline() && (object->isBeforeContent() || object->isAfterContent())) | |
+ || (object->isAnonymous() && object->isRenderBlock() && object->style()->display() == INLINE_BLOCK)); | |
+ | |
+ return object | |
+ && object->parent()->isRuby() | |
+ && object->isRenderBlock() | |
+ && !object->isRubyRun(); | |
+} | |
+ | |
+static inline bool isRubyBeforeBlock(const RenderObject* object) | |
+{ | |
+ return isAnonymousRubyInlineBlock(object) | |
+ && !object->previousSibling() | |
+ && object->firstChild() | |
+ && object->firstChild()->style()->styleType() == BEFORE; | |
+} | |
+ | |
+static inline bool isRubyAfterBlock(const RenderObject* object) | |
+{ | |
+ return isAnonymousRubyInlineBlock(object) | |
+ && !object->nextSibling() | |
+ && object->firstChild() | |
+ && object->firstChild()->style()->styleType() == AFTER; | |
+} | |
+ | |
+static inline RenderBlock* rubyBeforeBlock(const RenderObject* ruby) | |
+{ | |
+ RenderObject* child = ruby->firstChild(); | |
+ return isRubyBeforeBlock(child) ? static_cast<RenderBlock*>(child) : 0; | |
+} | |
+ | |
+static inline RenderBlock* rubyAfterBlock(const RenderObject* ruby) | |
+{ | |
+ RenderObject* child = ruby->lastChild(); | |
+ return isRubyAfterBlock(child) ? static_cast<RenderBlock*>(child) : 0; | |
+} | |
+ | |
+static RenderBlock* createAnonymousRubyInlineBlock(RenderObject* ruby) | |
+{ | |
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(ruby->style()); | |
+ newStyle->setDisplay(INLINE_BLOCK); | |
+ | |
+ RenderBlock* newBlock = new (ruby->renderArena()) RenderBlock(ruby->document() /* anonymous box */); | |
+ newBlock->setStyle(newStyle.release()); | |
+ return newBlock; | |
+} | |
static RenderRubyRun* lastRubyRun(const RenderObject* ruby) | |
{ | |
RenderObject* child = ruby->lastChild(); | |
- if (child && ruby->isAfterContent(child)) | |
+ if (child && !child->isRubyRun()) | |
child = child->previousSibling(); | |
- ASSERT(!child || child->isRubyRun()); | |
- return static_cast<RenderRubyRun*>(child); | |
+ ASSERT(!child || child->isRubyRun() || child->isBeforeContent() || child == rubyBeforeBlock(ruby)); | |
+ return child && child->isRubyRun() ? static_cast<RenderRubyRun*>(child) : 0; | |
} | |
static inline RenderRubyRun* findRubyRunParent(RenderObject* child) | |
@@ -64,18 +117,41 @@ RenderRubyAsInline::~RenderRubyAsInline() | |
{ | |
} | |
-bool RenderRubyAsInline::isChildAllowed(RenderObject* child, RenderStyle*) const | |
-{ | |
- return child->isRubyText() | |
- || child->isRubyRun() | |
- || child->isInline(); | |
-} | |
- | |
void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild) | |
{ | |
- // Note: ':after' content is handled implicitely below | |
+ // Insert :before and :after content before/after the RenderRubyRun(s) | |
+ if (child->isBeforeContent()) { | |
+ if (child->isInline()) { | |
+ // Add generated inline content normally | |
+ RenderInline::addChild(child, firstChild()); | |
+ } else { | |
+ // Wrap non-inline content with an anonymous inline-block. | |
+ RenderBlock* beforeBlock = rubyBeforeBlock(this); | |
+ if (!beforeBlock) { | |
+ beforeBlock = createAnonymousRubyInlineBlock(this); | |
+ RenderInline::addChild(beforeBlock, firstChild()); | |
+ } | |
+ beforeBlock->addChild(child); | |
+ } | |
+ return; | |
+ } | |
+ if (child->isAfterContent()) { | |
+ if (child->isInline()) { | |
+ // Add generated inline content normally | |
+ RenderInline::addChild(child); | |
+ } else { | |
+ // Wrap non-inline content with an anonymous inline-block. | |
+ RenderBlock* afterBlock = rubyAfterBlock(this); | |
+ if (!afterBlock) { | |
+ afterBlock = createAnonymousRubyInlineBlock(this); | |
+ RenderInline::addChild(afterBlock); | |
+ } | |
+ afterBlock->addChild(child); | |
+ } | |
+ return; | |
+ } | |
- // if child is a ruby run, just add it normally | |
+ // If the child is a ruby run, just add it normally. | |
if (child->isRubyRun()) { | |
RenderInline::addChild(child, beforeChild); | |
return; | |
@@ -84,13 +160,14 @@ void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild | |
if (beforeChild && !isAfterContent(beforeChild)) { | |
// insert child into run | |
ASSERT(!beforeChild->isRubyRun()); | |
- RenderRubyRun* run = findRubyRunParent(beforeChild); | |
- ASSERT(run); // beforeChild should always have a run as parent | |
+ RenderObject* run = beforeChild; | |
+ while (run && !run->isRubyRun()) | |
+ run = run->parent(); | |
if (run) { | |
run->addChild(child, beforeChild); | |
return; | |
} | |
- ASSERT(false); // beforeChild should always have a run as parent! | |
+ ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent! | |
// Emergency fallback: fall through and just append. | |
} | |
@@ -107,15 +184,24 @@ void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild | |
void RenderRubyAsInline::removeChild(RenderObject* child) | |
{ | |
- // If the child's parent is *this, i.e. a ruby run or ':after' content, | |
+ // If the child's parent is *this (must be a ruby run or generated content or anonymous block), | |
// just use the normal remove method. | |
if (child->parent() == this) { | |
- ASSERT(child->isRubyRun() || child->isAfterContent()); | |
+ ASSERT(child->isRubyRun() || child->isBeforeContent() || child->isAfterContent() || isAnonymousRubyInlineBlock(child)); | |
RenderInline::removeChild(child); | |
return; | |
} | |
+ // If the child's parent is an anoymous block (must be generated :before/:after content) | |
+ // just use the block's remove method. | |
+ if (isAnonymousRubyInlineBlock(child->parent())) { | |
+ ASSERT(child->isBeforeContent() || child->isAfterContent()); | |
+ child->parent()->removeChild(child); | |
+ removeChild(child->parent()); | |
+ return; | |
+ } | |
- // Find the containing run | |
+ // Otherwise find the containing run and remove it from there. | |
+ ASSERT(child->parent() != this); | |
RenderRubyRun* run = findRubyRunParent(child); | |
ASSERT(run); | |
run->removeChild(child); | |
@@ -133,18 +219,41 @@ RenderRubyAsBlock::~RenderRubyAsBlock() | |
{ | |
} | |
-bool RenderRubyAsBlock::isChildAllowed(RenderObject* child, RenderStyle*) const | |
-{ | |
- return child->isRubyText() | |
- || child->isRubyRun() | |
- || child->isInline(); | |
-} | |
- | |
void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild) | |
{ | |
- // Note: ':after' content is handled implicitely below | |
+ // Insert :before and :after content before/after the RenderRubyRun(s) | |
+ if (child->isBeforeContent()) { | |
+ if (child->isInline()) { | |
+ // Add generated inline content normally | |
+ RenderBlock::addChild(child, firstChild()); | |
+ } else { | |
+ // Wrap non-inline content with an anonymous inline-block. | |
+ RenderBlock* beforeBlock = rubyBeforeBlock(this); | |
+ if (!beforeBlock) { | |
+ beforeBlock = createAnonymousRubyInlineBlock(this); | |
+ RenderBlock::addChild(beforeBlock, firstChild()); | |
+ } | |
+ beforeBlock->addChild(child); | |
+ } | |
+ return; | |
+ } | |
+ if (child->isAfterContent()) { | |
+ if (child->isInline()) { | |
+ // Add generated inline content normally | |
+ RenderBlock::addChild(child); | |
+ } else { | |
+ // Wrap non-inline content with an anonymous inline-block. | |
+ RenderBlock* afterBlock = rubyAfterBlock(this); | |
+ if (!afterBlock) { | |
+ afterBlock = createAnonymousRubyInlineBlock(this); | |
+ RenderBlock::addChild(afterBlock); | |
+ } | |
+ afterBlock->addChild(child); | |
+ } | |
+ return; | |
+ } | |
- // if child is a ruby run, just add it normally | |
+ // If the child is a ruby run, just add it normally. | |
if (child->isRubyRun()) { | |
RenderBlock::addChild(child, beforeChild); | |
return; | |
@@ -160,7 +269,7 @@ void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild) | |
run->addChild(child, beforeChild); | |
return; | |
} | |
- ASSERT(false); // beforeChild should always have a run as parent! | |
+ ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent! | |
// Emergency fallback: fall through and just append. | |
} | |
@@ -177,14 +286,23 @@ void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild) | |
void RenderRubyAsBlock::removeChild(RenderObject* child) | |
{ | |
- // If the child's parent is *this, just use the normal remove method. | |
+ // If the child's parent is *this (must be a ruby run or generated content or anonymous block), | |
+ // just use the normal remove method. | |
if (child->parent() == this) { | |
- // This should happen only during destruction of the whole ruby element, though. | |
+ ASSERT(child->isRubyRun() || child->isBeforeContent() || child->isAfterContent() || isAnonymousRubyInlineBlock(child)); | |
RenderBlock::removeChild(child); | |
return; | |
} | |
+ // If the child's parent is an anoymous block (must be generated :before/:after content) | |
+ // just use the block's remove method. | |
+ if (isAnonymousRubyInlineBlock(child->parent())) { | |
+ ASSERT(child->isBeforeContent() || child->isAfterContent()); | |
+ child->parent()->removeChild(child); | |
+ removeChild(child->parent()); | |
+ return; | |
+ } | |
- // Find the containing run | |
+ // Otherwise find the containing run and remove it from there. | |
RenderRubyRun* run = findRubyRunParent(child); | |
ASSERT(run); | |
run->removeChild(child); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderRuby.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderRuby.h | |
index 49a84d8..24ac0db 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderRuby.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderRuby.h | |
@@ -47,6 +47,8 @@ namespace WebCore { | |
// 1-n inline object(s) | |
// | |
// Note: <rp> elements are defined as having 'display:none' and thus normally are not assigned a renderer. | |
+// | |
+// Generated :before/:after content is shunted into anonymous inline blocks | |
// <ruby> when used as 'display:inline' | |
class RenderRubyAsInline : public RenderInline { | |
@@ -54,7 +56,6 @@ public: | |
RenderRubyAsInline(Node*); | |
virtual ~RenderRubyAsInline(); | |
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; | |
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); | |
virtual void removeChild(RenderObject* child); | |
@@ -71,7 +72,6 @@ public: | |
RenderRubyAsBlock(Node*); | |
virtual ~RenderRubyAsBlock(); | |
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; | |
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); | |
virtual void removeChild(RenderObject* child); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderRubyBase.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderRubyBase.cpp | |
index da28953..9956f97 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderRubyBase.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderRubyBase.cpp | |
@@ -50,139 +50,81 @@ bool RenderRubyBase::isChildAllowed(RenderObject* child, RenderStyle*) const | |
#if 1 | |
// modified at webkit.org trunk r53525 | |
-bool RenderRubyBase::hasOnlyWrappedInlineChildren(RenderObject* beforeChild) const | |
-{ | |
- // Tests whether all children in the base before beforeChild are either floated/positioned, | |
- // or inline objects wrapped in anonymous blocks. | |
- // Note that beforeChild may be 0, in which case all children are looked at. | |
- for (RenderObject* child = firstChild(); child != beforeChild; child = child->nextSibling()) { | |
- if (!child->isFloatingOrPositioned() && !(child->isAnonymousBlock() && child->childrenInline())) | |
- return false; | |
- } | |
- return true; | |
-} | |
- | |
-void RenderRubyBase::moveChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild) | |
-{ | |
- // This function removes all children that are before (!) beforeChild | |
- // and appends them to toBase. | |
- ASSERT(toBase); | |
- | |
- // First make sure that beforeChild (if set) is indeed a direct child of this. | |
- // Inline children might be wrapped in an anonymous block if there's a continuation. | |
- // Theoretically, in ruby bases, this can happen with only the first such a child, | |
- // so it should be OK to just climb the tree. | |
- while (fromBeforeChild && fromBeforeChild->parent() != this) | |
- fromBeforeChild = fromBeforeChild->parent(); | |
- | |
- if (childrenInline()) | |
- moveInlineChildren(toBase, fromBeforeChild); | |
- else | |
- moveBlockChildren(toBase, fromBeforeChild); | |
- | |
- setNeedsLayoutAndPrefWidthsRecalc(); | |
- toBase->setNeedsLayoutAndPrefWidthsRecalc(); | |
-} | |
- | |
-void RenderRubyBase::moveInlineChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild) | |
-{ | |
- RenderBlock* toBlock; | |
- | |
- if (toBase->childrenInline()) { | |
- // The standard and easy case: move the children into the target base | |
- toBlock = toBase; | |
- } else { | |
- // We need to wrap the inline objects into an anonymous block. | |
- // If toBase has a suitable block, we re-use it, otherwise create a new one. | |
- RenderObject* lastChild = toBase->lastChild(); | |
- if (lastChild && lastChild->isAnonymousBlock() && lastChild->childrenInline()) | |
- toBlock = toRenderBlock(lastChild); | |
- else { | |
- toBlock = toBase->createAnonymousBlock(); | |
- toBase->children()->appendChildNode(toBase, toBlock); | |
- } | |
- } | |
- // Move our inline children into the target block we determined above. | |
- for (RenderObject* child = firstChild(); child != fromBeforeChild; child = firstChild()) | |
- moveChildTo(toBlock, toBlock->children(), child); | |
-} | |
- | |
-void RenderRubyBase::moveBlockChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild) | |
-{ | |
- if (toBase->childrenInline()) { | |
- // First check whether we move only wrapped inline objects. | |
- if (hasOnlyWrappedInlineChildren(fromBeforeChild)) { | |
- // The reason why the base is in block flow must be after beforeChild. | |
- // We therefore can extract the inline objects and move them to toBase. | |
- for (RenderObject* child = firstChild(); child != fromBeforeChild; child = firstChild()) { | |
- if (child->isAnonymousBlock()) { | |
- RenderBlock* anonBlock = toRenderBlock(child); | |
- ASSERT(anonBlock->childrenInline()); | |
- ASSERT(!anonBlock->inlineContinuation()); | |
- anonBlock->moveAllChildrenTo(toBase, toBase->children()); | |
- anonBlock->deleteLineBoxTree(); | |
- anonBlock->destroy(); | |
- } else { | |
- ASSERT(child->isFloatingOrPositioned()); | |
- moveChildTo(toBase, toBase->children(), child); | |
- } | |
- } | |
- } else { | |
- // Moving block children -> have to set toBase as block flow | |
- toBase->makeChildrenNonInline(); | |
- // Move children, potentially collapsing anonymous block wrappers. | |
- mergeBlockChildren(toBase, fromBeforeChild); | |
- | |
- // Now we need to check if the leftover children are all inline. | |
- // If so, make this base inline again. | |
- if (hasOnlyWrappedInlineChildren()) { | |
- RenderObject* next = 0; | |
- for (RenderObject* child = firstChild(); child; child = next) { | |
- next = child->nextSibling(); | |
- if (child->isFloatingOrPositioned()) | |
- continue; | |
- ASSERT(child->isAnonymousBlock()); | |
- | |
- RenderBlock* anonBlock = toRenderBlock(child); | |
- ASSERT(anonBlock->childrenInline()); | |
- ASSERT(!anonBlock->inlineContinuation()); | |
- // Move inline children out of anonymous block. | |
- anonBlock->moveAllChildrenTo(this, children(), anonBlock); | |
- anonBlock->deleteLineBoxTree(); | |
- anonBlock->destroy(); | |
- } | |
- setChildrenInline(true); | |
- } | |
- } | |
- } else | |
- mergeBlockChildren(toBase, fromBeforeChild); | |
-} | |
- | |
-void RenderRubyBase::mergeBlockChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild) | |
-{ | |
- // This function removes all children that are before fromBeforeChild and appends them to toBase. | |
- ASSERT(!childrenInline()); | |
- ASSERT(toBase); | |
- ASSERT(!toBase->childrenInline()); | |
- | |
- // Quick check whether we have anything to do, to simplify the following code. | |
- if (fromBeforeChild != firstChild()) | |
- return; | |
- | |
- // If an anonymous block would be put next to another such block, then merge those. | |
- RenderObject* firstChildHere = firstChild(); | |
- RenderObject* lastChildThere = toBase->lastChild(); | |
- if (firstChildHere && firstChildHere->isAnonymousBlock() && firstChildHere->childrenInline() | |
- && lastChildThere && lastChildThere->isAnonymousBlock() && lastChildThere->childrenInline()) { | |
- RenderBlock* anonBlockHere = toRenderBlock(firstChildHere); | |
- RenderBlock* anonBlockThere = toRenderBlock(lastChildThere); | |
- anonBlockHere->moveAllChildrenTo(anonBlockThere, anonBlockThere->children()); | |
- anonBlockHere->deleteLineBoxTree(); | |
- anonBlockHere->destroy(); | |
- } | |
- // Move all remaining children normally. | |
- for (RenderObject* child = firstChild(); child != fromBeforeChild; child = firstChild()) | |
- moveChildTo(toBase, toBase->children(), child); | |
+void RenderRubyBase::moveChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild) | |
+{ | |
+ // This function removes all children that are before (!) beforeChild | |
+ // and appends them to toBase. | |
+ ASSERT_ARG(toBase, toBase); | |
+ | |
+ // First make sure that beforeChild (if set) is indeed a direct child of this. | |
+ // Inline children might be wrapped in an anonymous block if there's a continuation. | |
+ // Theoretically, in ruby bases, this can happen with only the first such a child, | |
+ // so it should be OK to just climb the tree. | |
+ while (fromBeforeChild && fromBeforeChild->parent() != this) | |
+ fromBeforeChild = fromBeforeChild->parent(); | |
+ | |
+ if (childrenInline()) | |
+ moveInlineChildren(toBase, fromBeforeChild); | |
+ else | |
+ moveBlockChildren(toBase, fromBeforeChild); | |
+ | |
+ setNeedsLayoutAndPrefWidthsRecalc(); | |
+ toBase->setNeedsLayoutAndPrefWidthsRecalc(); | |
+} | |
+ | |
+void RenderRubyBase::moveInlineChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild) | |
+{ | |
+ ASSERT(childrenInline()); | |
+ ASSERT_ARG(toBase, toBase); | |
+ | |
+ if (!firstChild()) | |
+ return; | |
+ | |
+ RenderBlock* toBlock; | |
+ if (toBase->childrenInline()) { | |
+ // The standard and easy case: move the children into the target base | |
+ toBlock = toBase; | |
+ } else { | |
+ // We need to wrap the inline objects into an anonymous block. | |
+ // If toBase has a suitable block, we re-use it, otherwise create a new one. | |
+ RenderObject* lastChild = toBase->lastChild(); | |
+ if (lastChild && lastChild->isAnonymousBlock() && lastChild->childrenInline()) | |
+ toBlock = toRenderBlock(lastChild); | |
+ else { | |
+ toBlock = toBase->createAnonymousBlock(); | |
+ toBase->children()->appendChildNode(toBase, toBlock); | |
+ } | |
+ } | |
+ // Move our inline children into the target block we determined above. | |
+ for (RenderObject* child = firstChild(); child != fromBeforeChild; child = firstChild()) | |
+ moveChildTo(toBlock, toBlock->children(), child); | |
+} | |
+ | |
+void RenderRubyBase::moveBlockChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild) | |
+{ | |
+ ASSERT(!childrenInline()); | |
+ ASSERT_ARG(toBase, toBase); | |
+ | |
+ if (!firstChild()) | |
+ return; | |
+ | |
+ if (toBase->childrenInline()) | |
+ toBase->makeChildrenNonInline(); | |
+ | |
+ // If an anonymous block would be put next to another such block, then merge those. | |
+ RenderObject* firstChildHere = firstChild(); | |
+ RenderObject* lastChildThere = toBase->lastChild(); | |
+ if (firstChildHere->isAnonymousBlock() && firstChildHere->childrenInline() | |
+ && lastChildThere && lastChildThere->isAnonymousBlock() && lastChildThere->childrenInline()) { | |
+ RenderBlock* anonBlockHere = toRenderBlock(firstChildHere); | |
+ RenderBlock* anonBlockThere = toRenderBlock(lastChildThere); | |
+ anonBlockHere->moveAllChildrenTo(anonBlockThere, anonBlockThere->children()); | |
+ anonBlockHere->deleteLineBoxTree(); | |
+ anonBlockHere->destroy(); | |
+ } | |
+ // Move all remaining children normally. | |
+ for (RenderObject* child = firstChild(); child != fromBeforeChild; child = firstChild()) | |
+ moveChildTo(toBase, toBase->children(), child); | |
} | |
#else | |
void RenderRubyBase::splitToLeft(RenderBlock* leftBase, RenderObject* beforeChild) | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderRubyBase.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderRubyBase.h | |
index 408aeda..959d590 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderRubyBase.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderRubyBase.h | |
@@ -51,15 +51,12 @@ public: | |
void mergeWithRight(RenderBlock* rightBase); | |
#else | |
// modified at webkit.org trunk r53525 | |
-private: | |
- bool hasOnlyWrappedInlineChildren(RenderObject* beforeChild = 0) const; | |
- | |
- void moveChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild = 0); | |
- void moveInlineChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild = 0); | |
- void moveBlockChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild = 0); | |
- void mergeBlockChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild = 0); | |
- | |
- // Allow RenderRubyRun to manipulate the children within ruby bases. | |
+private: | |
+ void moveChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild = 0); | |
+ void moveInlineChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild = 0); | |
+ void moveBlockChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild = 0); | |
+ | |
+ // Allow RenderRubyRun to manipulate the children within ruby bases. | |
friend class RenderRubyRun; | |
#endif | |
}; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderSlider.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderSlider.cpp | |
index 1dd3dbd..58ace33 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderSlider.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderSlider.cpp | |
@@ -212,25 +212,47 @@ void SliderThumbElement::detach() | |
HTMLDivElement::detach(); | |
} | |
+#if PLATFORM(WKC) | |
+static Vector<RenderSlider*>* gValidInstances = 0; | |
+#define ISVALIDINSTANCE() (gValidInstances->find(this)!=notFound) | |
+#endif | |
+ | |
RenderSlider::RenderSlider(HTMLInputElement* element) | |
: RenderBlock(element) | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!gValidInstances) | |
+ gValidInstances = new Vector<RenderSlider*>(); | |
+ gValidInstances->append(this); | |
+#endif | |
} | |
RenderSlider::~RenderSlider() | |
{ | |
if (m_thumb) | |
m_thumb->detach(); | |
- m_thumb = 0; | |
+#if PLATFORM(WKC) | |
+ size_t p = gValidInstances->find(this); | |
+ if (p!=notFound) | |
+ gValidInstances->remove(p); | |
+#endif | |
} | |
int RenderSlider::baselinePosition(bool, bool) const | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return 0; | |
+#endif | |
return height() + marginTop(); | |
} | |
void RenderSlider::calcPrefWidths() | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return; | |
+#endif | |
m_minPrefWidth = 0; | |
m_maxPrefWidth = 0; | |
@@ -261,6 +283,10 @@ void RenderSlider::calcPrefWidths() | |
void RenderSlider::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return; | |
+#endif | |
RenderBlock::styleDidChange(diff, oldStyle); | |
if (m_thumb) | |
@@ -271,6 +297,10 @@ void RenderSlider::styleDidChange(StyleDifference diff, const RenderStyle* oldSt | |
PassRefPtr<RenderStyle> RenderSlider::createThumbStyle(const RenderStyle* parentStyle) | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return 0; | |
+#endif | |
RefPtr<RenderStyle> style; | |
RenderStyle* pseudoStyle = getCachedPseudoStyle(SLIDER_THUMB); | |
if (pseudoStyle) | |
@@ -298,6 +328,10 @@ PassRefPtr<RenderStyle> RenderSlider::createThumbStyle(const RenderStyle* parent | |
IntRect RenderSlider::thumbRect() | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return IntRect(); | |
+#endif | |
if (!m_thumb) | |
return IntRect(); | |
@@ -322,6 +356,10 @@ IntRect RenderSlider::thumbRect() | |
void RenderSlider::layout() | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return; | |
+#endif | |
ASSERT(needsLayout()); | |
RenderBox* thumb = m_thumb ? toRenderBox(m_thumb->renderer()) : 0; | |
@@ -373,6 +411,10 @@ void RenderSlider::layout() | |
void RenderSlider::updateFromElement() | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return; | |
+#endif | |
HTMLInputElement* element = static_cast<HTMLInputElement*>(node()); | |
// Send the value back to the element if the range changes it. | |
@@ -397,6 +439,10 @@ void RenderSlider::updateFromElement() | |
bool RenderSlider::mouseEventIsInThumb(MouseEvent* evt) | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return false; | |
+#endif | |
if (!m_thumb || !m_thumb->renderer()) | |
return false; | |
@@ -414,6 +460,10 @@ bool RenderSlider::mouseEventIsInThumb(MouseEvent* evt) | |
FloatPoint RenderSlider::mouseEventOffsetToThumb(MouseEvent* evt) | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return FloatPoint(); | |
+#endif | |
ASSERT(m_thumb && m_thumb->renderer()); | |
FloatPoint localPoint = m_thumb->renderBox()->absoluteToLocal(evt->absoluteLocation(), false, true); | |
IntRect thumbBounds = m_thumb->renderBox()->borderBoxRect(); | |
@@ -425,6 +475,10 @@ FloatPoint RenderSlider::mouseEventOffsetToThumb(MouseEvent* evt) | |
void RenderSlider::setValueForPosition(int position) | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return; | |
+#endif | |
if (!m_thumb || !m_thumb->renderer()) | |
return; | |
@@ -450,6 +504,10 @@ void RenderSlider::setValueForPosition(int position) | |
int RenderSlider::positionForOffset(const IntPoint& p) | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return 0; | |
+#endif | |
if (!m_thumb || !m_thumb->renderer()) | |
return 0; | |
@@ -464,6 +522,10 @@ int RenderSlider::positionForOffset(const IntPoint& p) | |
int RenderSlider::currentPosition() | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return 0; | |
+#endif | |
ASSERT(m_thumb); | |
ASSERT(m_thumb->renderer()); | |
@@ -474,6 +536,10 @@ int RenderSlider::currentPosition() | |
int RenderSlider::trackSize() | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return 0; | |
+#endif | |
ASSERT(m_thumb); | |
ASSERT(m_thumb->renderer()); | |
@@ -484,6 +550,10 @@ int RenderSlider::trackSize() | |
void RenderSlider::forwardEvent(Event* event) | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return; | |
+#endif | |
if (event->isMouseEvent()) { | |
MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); | |
if (event->type() == eventNames().mousedownEvent && mouseEvent->button() == LeftButton) { | |
@@ -494,13 +564,25 @@ void RenderSlider::forwardEvent(Event* event) | |
} | |
} | |
- if (m_thumb) | |
- m_thumb->defaultEventHandler(event); | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return; | |
+#endif | |
+ m_thumb->defaultEventHandler(event); | |
} | |
bool RenderSlider::inDragMode() const | |
{ | |
+#if PLATFORM(WKC) | |
+ if (!ISVALIDINSTANCE()) | |
+ return false; | |
+#endif | |
return m_thumb && m_thumb->inDragMode(); | |
} | |
+void RenderSlider_resetVariables() | |
+{ | |
+ gValidInstances = 0; | |
+} | |
+ | |
} // namespace WebCore | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTable.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTable.h | |
index 9b6f318..e8fa216 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTable.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTable.h | |
@@ -74,7 +74,7 @@ public: | |
{ | |
} | |
- unsigned short span; | |
+ unsigned span; | |
unsigned width; // the calculated position of the column | |
}; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTableRow.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTableRow.cpp | |
index 7afc3be..1cf0d1d 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTableRow.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTableRow.cpp | |
@@ -73,13 +73,13 @@ void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild) | |
RenderObject* last = beforeChild; | |
if (!last) | |
last = lastChild(); | |
- if (last && last->isAnonymous() && last->isTableCell()) { | |
+ if (last && last->isAnonymous() && last->isTableCell() && !isAfterContent(last) && !isBeforeContent(last)) { | |
last->addChild(child); | |
return; | |
} | |
// If beforeChild is inside an anonymous cell, insert into the cell. | |
- if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous()) { | |
+ if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous() && !isAfterContent(last->parent()) && !isBeforeContent(last->parent())) { | |
last->parent()->addChild(child, beforeChild); | |
return; | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTableSection.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTableSection.cpp | |
index 427f56f..4f68165 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTableSection.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTableSection.cpp | |
@@ -98,7 +98,7 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild | |
RenderObject* last = beforeChild; | |
if (!last) | |
last = lastChild(); | |
- if (last && last->isAnonymous()) { | |
+ if (last && last->isAnonymous() && !isAfterContent(last) && !isBeforeContent(last)) { | |
last->addChild(child); | |
return; | |
} | |
@@ -108,7 +108,7 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild | |
RenderObject* lastBox = last; | |
while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableRow()) | |
lastBox = lastBox->parent(); | |
- if (lastBox && lastBox->isAnonymous()) { | |
+ if (lastBox && lastBox->isAnonymous() && !isAfterContent(lastBox) && !isBeforeContent(lastBox)) { | |
lastBox->addChild(child, beforeChild); | |
return; | |
} | |
@@ -236,7 +236,7 @@ void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row) | |
table()->appendColumn(cSpan); | |
currentSpan = cSpan; | |
} else { | |
- if (cSpan < columns[m_cCol].span) | |
+ if (cSpan < static_cast<int>(columns[m_cCol].span)) | |
table()->splitColumn(m_cCol, cSpan); | |
currentSpan = columns[m_cCol].span; | |
} | |
@@ -1217,6 +1217,13 @@ void RenderTableSection::recalcCells() | |
setNeedsLayout(true); | |
} | |
+void RenderTableSection::setNeedsCellRecalc() | |
+{ | |
+ m_needsCellRecalc = true; | |
+ if (RenderTable* t = table()) | |
+ t->setNeedsSectionRecalc(); | |
+} | |
+ | |
void RenderTableSection::clearGrid() | |
{ | |
int rows = m_gridRows; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTableSection.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTableSection.h | |
index 9f6d5ea..97ce8c4 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTableSection.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTableSection.h | |
@@ -94,11 +94,7 @@ public: | |
} | |
bool needsCellRecalc() const { return m_needsCellRecalc; } | |
- void setNeedsCellRecalc() | |
- { | |
- m_needsCellRecalc = true; | |
- table()->setNeedsSectionRecalc(); | |
- } | |
+ void setNeedsCellRecalc(); | |
int getBaseline(int row) { return m_grid[row].baseline; } | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderText.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderText.cpp | |
index 6399ce2..f2acf0c 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderText.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderText.cpp | |
@@ -4,7 +4,7 @@ | |
* Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. | |
* Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) | |
* Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) | |
- * Copyright (c) 2011 ACCESS CO., LTD. All rights reserved. | |
+ * Copyright (c) 2011 ACCESS CO., LTD. All rights reserved. | |
* | |
* This library is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU Library General Public | |
@@ -1027,9 +1027,9 @@ int RenderText::lineHeight(bool firstLine, bool) const | |
void RenderText::dirtyLineBoxes(bool fullLayout) | |
{ | |
-#if PLATFORM(WKC) | |
- CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); | |
-#endif | |
+#if PLATFORM(WKC) | |
+ CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); | |
+#endif | |
if (fullLayout) | |
deleteTextBoxes(); | |
else if (!m_linesDirty) { | |
@@ -1068,13 +1068,13 @@ void RenderText::positionLineBox(InlineBox* box) | |
s->remove(); | |
#if 1 | |
// webkit trunk r52527 | |
- if (m_firstTextBox == s) | |
- m_firstTextBox = s->nextTextBox(); | |
- else | |
- s->prevTextBox()->setNextLineBox(s->nextTextBox()); | |
- if (m_lastTextBox == s) | |
- m_lastTextBox = s->prevTextBox(); | |
- else | |
+ if (m_firstTextBox == s) | |
+ m_firstTextBox = s->nextTextBox(); | |
+ else | |
+ s->prevTextBox()->setNextLineBox(s->nextTextBox()); | |
+ if (m_lastTextBox == s) | |
+ m_lastTextBox = s->prevTextBox(); | |
+ else | |
s->nextTextBox()->setPreviousLineBox(s->prevTextBox()); | |
#endif | |
s->destroy(renderArena()); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTextControl.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTextControl.cpp | |
index cea155e..194f385 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTextControl.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTextControl.cpp | |
@@ -373,8 +373,6 @@ String RenderTextControl::textWithHardLineBreaks() | |
if (!firstChild) | |
return ""; | |
- document()->updateLayout(); | |
- | |
RenderObject* renderer = firstChild->renderer(); | |
if (!renderer) | |
return ""; | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTextControlSingleLine.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTextControlSingleLine.cpp | |
index be09d01..46c5aea 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTextControlSingleLine.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTextControlSingleLine.cpp | |
@@ -415,7 +415,7 @@ int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const | |
void RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight(int lineHeight) | |
{ | |
if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) { | |
- toRenderBlock(resultsRenderer)->calcHeight(); | |
+ resultsRenderer->calcHeight(); | |
setHeight(max(height(), | |
resultsRenderer->borderTop() + resultsRenderer->borderBottom() + | |
resultsRenderer->paddingTop() + resultsRenderer->paddingBottom() + | |
@@ -424,7 +424,7 @@ void RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight(int lineH | |
} | |
if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) { | |
- toRenderBlock(cancelRenderer)->calcHeight(); | |
+ cancelRenderer->calcHeight(); | |
setHeight(max(height(), | |
cancelRenderer->borderTop() + cancelRenderer->borderBottom() + | |
cancelRenderer->paddingTop() + cancelRenderer->paddingBottom() + | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTextFragment.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTextFragment.cpp | |
index f35cbc0..f5386d6 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RenderTextFragment.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RenderTextFragment.cpp | |
@@ -47,12 +47,10 @@ RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str) | |
PassRefPtr<StringImpl> RenderTextFragment::originalText() const | |
{ | |
Node* e = node(); | |
-// RefPtr<StringImpl> result = (e ? static_cast<Text*>(e)->dataImpl() : contentString()); | |
- // r59795 | |
RefPtr<StringImpl> result = ((e && e->isTextNode()) ? static_cast<Text*>(e)->dataImpl() : contentString()); | |
- if (result && (start() > 0 || start() < result->length())) | |
- result = result->substring(start(), end()); | |
- return result.release(); | |
+ if (!result) | |
+ return 0; | |
+ return result->substring(start(), end()); | |
} | |
void RenderTextFragment::destroy() | |
@@ -73,9 +71,9 @@ void RenderTextFragment::setTextInternal(PassRefPtr<StringImpl> text) | |
m_end = textLength(); | |
#if 1 | |
// added at webkit.org trunk r55196 | |
- if (Node* t = node()) { | |
- ASSERT(!t->renderer()); | |
- t->setRenderer(this); | |
+ if (Node* t = node()) { | |
+ ASSERT(!t->renderer()); | |
+ t->setRenderer(this); | |
} | |
#endif | |
} | |
@@ -88,7 +86,7 @@ UChar RenderTextFragment::previousCharacter() | |
// StringImpl* original = (e ? static_cast<Text*>(e)->dataImpl() : contentString()); | |
// r59795 | |
StringImpl* original = ((e && e->isTextNode()) ? static_cast<Text*>(e)->dataImpl() : contentString()); | |
- if (original) | |
+ if (original && start() <= original->length()) | |
return (*original)[start() - 1]; | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RootInlineBox.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RootInlineBox.cpp | |
index 2919c14..13bf41f 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/RootInlineBox.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/RootInlineBox.cpp | |
@@ -250,7 +250,11 @@ int RootInlineBox::verticallyAlignBoxes(int heightOfBlock) | |
computeVerticalOverflow(lineTop, lineBottom, strictMode); | |
setLineTopBottomPositions(lineTop, lineBottom); | |
- heightOfBlock += maxHeight; | |
+ // Detect integer overflow. | |
+ if (heightOfBlock > numeric_limits<int>::max() - maxHeight) | |
+ return numeric_limits<int>::max(); | |
+ | |
+ heightOfBlock = heightOfBlock + maxHeight; | |
return heightOfBlock; | |
} | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/style/RenderStyle.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/style/RenderStyle.cpp | |
index 5d8fb25..6eb320e 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/style/RenderStyle.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/style/RenderStyle.cpp | |
@@ -64,6 +64,13 @@ PassRefPtr<RenderStyle> RenderStyle::createDefaultStyle() | |
return adoptRef(new RenderStyle(true)); | |
} | |
+PassRefPtr<RenderStyle> RenderStyle::createAnonymousStyle(const RenderStyle* parentStyle) | |
+{ | |
+ RefPtr<RenderStyle> newStyle = RenderStyle::create(); | |
+ newStyle->inheritFrom(parentStyle); | |
+ return newStyle; | |
+} | |
+ | |
PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other) | |
{ | |
return adoptRef(new RenderStyle(*other)); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/style/RenderStyle.h b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/style/RenderStyle.h | |
index 319760a..b687fa1 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/rendering/style/RenderStyle.h | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/rendering/style/RenderStyle.h | |
@@ -298,6 +298,7 @@ protected: | |
public: | |
static PassRefPtr<RenderStyle> create(); | |
static PassRefPtr<RenderStyle> createDefaultStyle(); | |
+ static PassRefPtr<RenderStyle> createAnonymousStyle(const RenderStyle* parentStyle); | |
static PassRefPtr<RenderStyle> clone(const RenderStyle*); | |
~RenderStyle(); | |
diff --git a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/websockets/WebSocketHandshake.cpp b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/websockets/WebSocketHandshake.cpp | |
index a568c2b..b91e6aa 100644 | |
--- a/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.2.0/webkit/WebCore/websockets/WebSocketHandshake.cpp | |
+++ b/3DS_InternetBrowser_OpenSources_JP_US_EU_KR_TW_HK_CN_10.6.0/webkit/WebCore/websockets/WebSocketHandshake.cpp | |
@@ -350,7 +350,8 @@ void WebSocketHandshake::setServerSetCookie2(const String& setCookie2) | |
KURL WebSocketHandshake::httpURLForAuthenticationAndCookies() const | |
{ | |
KURL url = m_url.copy(); | |
- url.setProtocol(m_secure ? "https" : "http"); | |
+ bool couldSetProtocol = url.setProtocol(m_secure ? "https" : "http"); | |
+ ASSERT_UNUSED(couldSetProtocol, couldSetProtocol); | |
return url; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment