NeverDestroyed<String>(ASCIILiteral(...)) is not thread safe.
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 May 2017 23:24:13 +0000 (23:24 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 May 2017 23:24:13 +0000 (23:24 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171586
<rdar://problem/31873190>

Reviewed by Yusuke Suzuki.

Source/JavaScriptCore:

JavaScriptCore allows multiple VMs to be instantiated, and each of these should
be able to run concurrently on different threads.  There is code in the VM that
allocates NeverDestroyed<String>(ASCIILiteral(...)) to defined immortal strings
meant to be shared by all VMs.

However, NeverDestroyed<String>(ASCIILiteral(...)) is not thread-safe because
each thread will ref and deref the underlying StringImpl.  Since this ref and
deref is not done in a thread-safe way, the NeverDestroyed<String> may get
destroyed due to the ref/deref races.  Additionally, each thread may modify the
StringImpl by setting its hash and also twiddling its flags.

The fix is to use the StaticStringImpl class which is safe for ref/derefing
concurrently from different threads.  StaticStringImpl is also pre-set with a
hash on construction, and its flags are set in such a way as to prevent twiddling
at runtime.  Hence, we will be able to share a NeverDestroyed<String> between
VMs, as long as it is backed by a StaticStringImpl.

An alternative solution would be to change all the uses of NeverDestroyed<String>
to use per-VM strings.  However, this solution is cumbersome, and makes it harder
to allocate the intended shared string.  It also uses more memory and takes more
CPU time because it requires allocating the same string for each VM instance.
The StaticStringImpl solution wins out because it is more efficient and is easier
to use.

The StaticStringImpl solution also can be used in WTF without a layer violation.
See Source/WTF/wtf/text/icu/TextBreakIteratorICU.h for an example.

Also added the MultithreadedMultiVMExecutionTest which runs multiple VMs in
multiple threads, all banging on the BuiltinExecutable's baseConstructorCode
NeverDestroyed<String>.  The test will manifest the issue reliably (before this
fix) if run on an ASAN build.

* API/tests/MultithreadedMultiVMExecutionTest.cpp: Added.
(threadsList):
(startMultithreadedMultiVMExecutionTest):
(finalizeMultithreadedMultiVMExecutionTest):
* API/tests/MultithreadedMultiVMExecutionTest.h: Added.
* API/tests/testapi.c:
(main):
* JavaScriptCore.xcodeproj/project.pbxproj:
* builtins/BuiltinExecutables.cpp:
(JSC::BuiltinExecutables::createDefaultConstructor):
* inspector/agents/InspectorDebuggerAgent.cpp:
(Inspector::objectGroupForBreakpointAction):
* replay/scripts/CodeGeneratorReplayInputsTemplates.py:
* replay/scripts/tests/expected/generate-enum-encoding-helpers-with-guarded-values.json-TestReplayInputs.cpp:
(JSC::InputTraits<Test::SavedMouseButton>::type):
* replay/scripts/tests/expected/generate-enum-encoding-helpers.json-TestReplayInputs.cpp:
(JSC::InputTraits<Test::SavedMouseButton>::type):
* replay/scripts/tests/expected/generate-enum-with-guard.json-TestReplayInputs.cpp:
(JSC::InputTraits<Test::HandleWheelEvent>::type):
* replay/scripts/tests/expected/generate-enums-with-same-base-name.json-TestReplayInputs.cpp:
(JSC::InputTraits<Test::FormCombo>::type):
* replay/scripts/tests/expected/generate-input-with-guard.json-TestReplayInputs.cpp:
(JSC::InputTraits<Test::GetCurrentTime>::type):
(JSC::InputTraits<Test::SetRandomSeed>::type):
* replay/scripts/tests/expected/generate-input-with-vector-members.json-TestReplayInputs.cpp:
(JSC::InputTraits<Test::ArrayOfThings>::type):
(JSC::InputTraits<Test::SavedHistory>::type):
* replay/scripts/tests/expected/generate-inputs-with-flags.json-TestReplayInputs.cpp:
(JSC::InputTraits<Test::ScalarInput1>::type):
(JSC::InputTraits<Test::ScalarInput2>::type):
* replay/scripts/tests/expected/generate-memoized-type-modes.json-TestReplayInputs.cpp:
(JSC::InputTraits<Test::ScalarInput>::type):
(JSC::InputTraits<Test::MapInput>::type):
* runtime/IntlObject.cpp:
(JSC::numberingSystemsForLocale):

Source/WebCore:

No new tests because we're just converting uses of ASCIILiteral (in the
instantiation of NeverDestroyed<String> and NeverDestroyed<const String>) to
MAKE_STATIC_STRING_IMPL.

The correctness of using MAKE_STATIC_STRING_IMPL is tested in the newly added
API test in this patch.

Also changed "static NeverDestroyed<ASCIILiteral>" instances in
SQLiteIDBBackingStore.cpp to "static const char* const" because they are only
ever used to get the underlying const char*.

* Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:
(WebCore::IDBServer::SQLiteIDBBackingStore::getRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::cachedStatementForGetAllObjectStoreRecords):
* Modules/mediastream/MediaEndpointSessionDescription.cpp:
* Modules/mediastream/RTCRtpTransceiver.cpp:
* Modules/mediastream/SDPProcessor.cpp:
* Modules/navigatorcontentutils/NavigatorContentUtils.cpp:
(WebCore::customHandlersStateString):
(WebCore::NavigatorContentUtils::isProtocolHandlerRegistered):
* Modules/speech/SpeechSynthesis.cpp:
(WebCore::SpeechSynthesis::boundaryEventOccurred):
* accessibility/AccessibilityMediaControls.cpp:
(WebCore::AccessibilityMediaControl::controlTypeName):
(WebCore::AccessibilityMediaControl::title):
(WebCore::AccessibilityMediaControlsContainer::elementTypeName):
(WebCore::AccessibilityMediaTimeline::helpText):
(WebCore::AccessibilityMediaTimeDisplay::accessibilityDescription):
* bindings/js/JSLazyEventListener.cpp:
(WebCore::eventParameterName):
* contentextensions/ContentExtensionsBackend.cpp:
(WebCore::ContentExtensions::ContentExtensionsBackend::displayNoneCSSRule):
* css/CSSDefaultStyleSheets.cpp:
(WebCore::screenEval):
(WebCore::printEval):
* css/MediaList.cpp:
(WebCore::addResolutionWarningMessageToConsole):
* css/StyleSheetContents.cpp:
(WebCore::StyleSheetContents::parseAuthorStyleSheet):
* dom/Document.cpp:
(WebCore::Document::readyState):
* dom/LoadableClassicScript.cpp:
(WebCore::LoadableClassicScript::notifyFinished):
* dom/PseudoElement.cpp:
(WebCore::PseudoElement::pseudoElementNameForEvents):
* editing/MarkupAccumulator.cpp:
(WebCore::MarkupAccumulator::shouldAddNamespaceElement):
* editing/cocoa/DataDetection.mm:
(WebCore::DataDetection::dataDetectorURLProtocol):
* editing/markup.cpp:
(WebCore::StyledMarkupAccumulator::styleNodeCloseTag):
(WebCore::createMarkupInternal):
* html/FormController.cpp:
(WebCore::formStateSignature):
* html/ImageInputType.cpp:
(WebCore::ImageInputType::appendFormData):
* html/canvas/CanvasRenderingContext2D.cpp:
(WebCore::CanvasRenderingContext2D::realizeSaves):
(WebCore::CanvasRenderingContext2D::getImageData):
* html/parser/XSSAuditor.cpp:
(WebCore::XSSAuditor::init):
(WebCore::XSSAuditor::eraseDangerousAttributesIfInjected):
* html/track/VTTCue.cpp:
(WebCore::startKeyword):
(WebCore::middleKeyword):
(WebCore::endKeyword):
(WebCore::leftKeyword):
(WebCore::rightKeyword):
(WebCore::verticalGrowingLeftKeyword):
(WebCore::verticalGrowingRightKeyword):
(WebCore::VTTCue::determineTextDirection):
(WebCore::VTTCue::markFutureAndPastNodes):
* inspector/InspectorCSSAgent.cpp:
(WebCore::computePseudoClassMask):
* inspector/InspectorIndexedDBAgent.cpp:
* inspector/InspectorPageAgent.cpp:
(WebCore::InspectorPageAgent::sourceMapURLForResource):
* inspector/PageDebuggerAgent.cpp:
(WebCore::PageDebuggerAgent::sourceMapURLForScript):
* loader/ImageLoader.cpp:
(WebCore::ImageLoader::notifyFinished):
* loader/TextTrackLoader.cpp:
(WebCore::TextTrackLoader::corsPolicyPreventedLoad):
* loader/icon/IconDatabase.cpp:
(WebCore::IconDatabase::defaultDatabaseFilename):
* page/CaptionUserPreferencesMediaAF.cpp:
(WebCore::CaptionUserPreferencesMediaAF::captionsTextEdgeCSS):
* page/SecurityOrigin.cpp:
(WebCore::SecurityOrigin::urlWithUniqueSecurityOrigin):
* page/UserContentURLPattern.cpp:
(WebCore::UserContentURLPattern::parse):
* platform/MIMETypeRegistry.cpp:
(WebCore::defaultMIMEType):
* platform/animation/Animation.cpp:
(WebCore::Animation::initialName):
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::engineDescription):
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::engineDescription):
* platform/graphics/cocoa/FontCacheCoreText.cpp:
(WebCore::FontCache::similarFont):
* platform/gtk/UserAgentGtk.cpp:
(WebCore::platformVersionForUAString):
* platform/mock/mediasource/MockBox.cpp:
(WebCore::MockTrackBox::type):
(WebCore::MockInitializationBox::type):
(WebCore::MockSampleBox::type):
* platform/network/HTTPHeaderValues.cpp:
(WebCore::HTTPHeaderValues::textPlainContentType):
(WebCore::HTTPHeaderValues::formURLEncodedContentType):
(WebCore::HTTPHeaderValues::noCache):
(WebCore::HTTPHeaderValues::maxAge0):
* platform/network/HTTPParsers.cpp:
(WebCore::parseXSSProtectionHeader):
* replay/MemoizedDOMResult.cpp:
(JSC::InputTraits<MemoizedDOMResultBase>::type):
* svg/SVGTransformValue.cpp:
(WebCore::SVGTransformValue::transformTypePrefixForParsing):

Source/WebKit2:

* Shared/API/APIError.cpp:
(API::Error::webKitErrorDomain):
(API::Error::webKitNetworkErrorDomain):
(API::Error::webKitPolicyErrorDomain):
(API::Error::webKitPluginErrorDomain):
(API::Error::webKitDownloadErrorDomain):
(API::Error::webKitPrintErrorDomain):
* Shared/WebPreferencesKeys.cpp:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::executeEditCommand):
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::didBeginEditing):
(WebKit::WebEditorClient::respondToChangedContents):
(WebKit::WebEditorClient::respondToChangedSelection):
(WebKit::WebEditorClient::didEndEditing):

Source/WTF:

StaticStringImpl is meant to be thread-safe.  However, it has a bug: it did not
set the s_hashFlagDidReportCost flag.  As a result, if cost() is called on it,
different threads may try to change its flags bits at the same time.  This patch
changes StaticStringImpl to always set the s_hashFlagDidReportCost flag.

Also factored out StringImplShape and made StringImpl and StaticStringImpl extend
it.  This makes it more clear that the 2 are intended to have the same shape.
Note: there is already a static_assert that the 2 have the same size.  This
change also ensures that they both have the same shape, which is a requirement in
order for StaticStringImpl to work.

Introduced the MAKE_STATIC_STRING_IMPL macro as a convenient way to instantiate
StaticStringImpls from literal strings.  This allows us to trivially change

    NeverDestroyed<String> myString(ASCIILiteral("myString"));

to ...

    NeverDestroyed<String> myString(MAKE_STATIC_STRING_IMPL("myString"));

and by so doing, make it thread-safe.

MAKE_STATIC_STRING_IMPL instantiates a lambda function to create the static
StaticStringImpls.

* wtf/text/StringImpl.h:
(WTF::StringImplShape::StringImplShape):
(WTF::StringImpl::StringImpl):
(WTF::StringImpl::cost):
(WTF::StringImpl::setHash):
(WTF::StringImpl::StaticStringImpl::StaticStringImpl):
(WTF::StringImpl::StaticStringImpl::operator StringImpl&):
* wtf/text/WTFString.h:
(WTF::String::String):
* wtf/text/icu/TextBreakIteratorICU.h:
(WTF::caretRules):

Tools:

API test for exercising StaticStringImpl and the MAKE_STATIC_STRING_IMPL macro.

* TestWebKitAPI/Tests/WTF/StringImpl.cpp:
(TestWebKitAPI::neverDestroyedString):
(TestWebKitAPI::getNeverDestroyedStringAtStackDepth):
(TestWebKitAPI::TEST):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@216217 268f45cc-cd09-0410-ab3c-d52691b4dbfc

73 files changed:
Source/JavaScriptCore/API/tests/MultithreadedMultiVMExecutionTest.cpp [new file with mode: 0644]
Source/JavaScriptCore/API/tests/MultithreadedMultiVMExecutionTest.h [new file with mode: 0644]
Source/JavaScriptCore/API/tests/testapi.c
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/builtins/BuiltinExecutables.cpp
Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp
Source/JavaScriptCore/replay/scripts/CodeGeneratorReplayInputsTemplates.py
Source/JavaScriptCore/replay/scripts/tests/expected/generate-enum-encoding-helpers-with-guarded-values.json-TestReplayInputs.cpp
Source/JavaScriptCore/replay/scripts/tests/expected/generate-enum-encoding-helpers.json-TestReplayInputs.cpp
Source/JavaScriptCore/replay/scripts/tests/expected/generate-enum-with-guard.json-TestReplayInputs.cpp
Source/JavaScriptCore/replay/scripts/tests/expected/generate-enums-with-same-base-name.json-TestReplayInputs.cpp
Source/JavaScriptCore/replay/scripts/tests/expected/generate-input-with-guard.json-TestReplayInputs.cpp
Source/JavaScriptCore/replay/scripts/tests/expected/generate-input-with-vector-members.json-TestReplayInputs.cpp
Source/JavaScriptCore/replay/scripts/tests/expected/generate-inputs-with-flags.json-TestReplayInputs.cpp
Source/JavaScriptCore/replay/scripts/tests/expected/generate-memoized-type-modes.json-TestReplayInputs.cpp
Source/JavaScriptCore/runtime/IntlObject.cpp
Source/WTF/ChangeLog
Source/WTF/wtf/text/StringImpl.h
Source/WTF/wtf/text/WTFString.h
Source/WTF/wtf/text/icu/TextBreakIteratorICU.h
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp
Source/WebCore/Modules/mediastream/MediaEndpointSessionDescription.cpp
Source/WebCore/Modules/mediastream/RTCRtpTransceiver.cpp
Source/WebCore/Modules/mediastream/SDPProcessor.cpp
Source/WebCore/Modules/navigatorcontentutils/NavigatorContentUtils.cpp
Source/WebCore/Modules/speech/SpeechSynthesis.cpp
Source/WebCore/accessibility/AccessibilityMediaControls.cpp
Source/WebCore/bindings/js/JSLazyEventListener.cpp
Source/WebCore/contentextensions/ContentExtensionsBackend.cpp
Source/WebCore/css/CSSDefaultStyleSheets.cpp
Source/WebCore/css/MediaList.cpp
Source/WebCore/css/StyleSheetContents.cpp
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/LoadableClassicScript.cpp
Source/WebCore/dom/PseudoElement.cpp
Source/WebCore/editing/MarkupAccumulator.cpp
Source/WebCore/editing/cocoa/DataDetection.mm
Source/WebCore/editing/markup.cpp
Source/WebCore/html/FormController.cpp
Source/WebCore/html/ImageInputType.cpp
Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
Source/WebCore/html/parser/XSSAuditor.cpp
Source/WebCore/html/track/VTTCue.cpp
Source/WebCore/inspector/InspectorCSSAgent.cpp
Source/WebCore/inspector/InspectorIndexedDBAgent.cpp
Source/WebCore/inspector/InspectorPageAgent.cpp
Source/WebCore/inspector/PageDebuggerAgent.cpp
Source/WebCore/loader/ImageLoader.cpp
Source/WebCore/loader/TextTrackLoader.cpp
Source/WebCore/loader/icon/IconDatabase.cpp
Source/WebCore/page/CaptionUserPreferencesMediaAF.cpp
Source/WebCore/page/SecurityOrigin.cpp
Source/WebCore/page/UserContentURLPattern.cpp
Source/WebCore/platform/MIMETypeRegistry.cpp
Source/WebCore/platform/animation/Animation.cpp
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm
Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp
Source/WebCore/platform/gtk/UserAgentGtk.cpp
Source/WebCore/platform/mock/mediasource/MockBox.cpp
Source/WebCore/platform/network/HTTPHeaderValues.cpp
Source/WebCore/platform/network/HTTPParsers.cpp
Source/WebCore/replay/MemoizedDOMResult.cpp
Source/WebCore/svg/SVGTransformValue.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/API/APIError.cpp
Source/WebKit2/Shared/WebPreferencesKeys.cpp
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp

diff --git a/Source/JavaScriptCore/API/tests/MultithreadedMultiVMExecutionTest.cpp b/Source/JavaScriptCore/API/tests/MultithreadedMultiVMExecutionTest.cpp
new file mode 100644 (file)
index 0000000..b1951a0
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MultithreadedMultiVMExecutionTest.h"
+
+#include "InitializeThreading.h"
+#include "JSContextRefPrivate.h"
+#include "JavaScriptCore.h"
+#include "Options.h"
+#include <mutex>
+#include <string>
+#include <thread>
+#include <vector>
+#include <wtf/MainThread.h>
+
+static int failuresFound = 0;
+
+static std::vector<std::thread>& threadsList()
+{
+    static std::vector<std::thread>* list;
+    static std::once_flag flag;
+    std::call_once(flag, [] () {
+        list = new std::vector<std::thread>();
+    });
+    return *list;
+}
+
+void startMultithreadedMultiVMExecutionTest()
+{
+    WTF::initializeMainThread();
+    JSC::initializeThreading();
+
+#define CHECK(condition, message) do { \
+        if (!condition) { \
+            printf("FAILED MultithreadedMultiVMExecutionTest: %s\n", message); \
+            failuresFound++; \
+        } \
+    } while (false)
+
+    auto task = [&]() {
+        int ret = 0;
+        std::string scriptString =
+            "const AAA = {A:0, B:1, C:2, D:3};"
+            "class Preconditions { static checkArgument(e,t) { if (!e) throw t }};"
+            "1 + 2";
+
+        for (int i = 0; i < 1000; ++i) {
+            JSClassRef jsClass = JSClassCreate(&kJSClassDefinitionEmpty);
+            CHECK(jsClass, "global object class creation");
+            JSContextGroupRef contextGroup = JSContextGroupCreate();
+            CHECK(contextGroup, "group creation");
+            JSGlobalContextRef context = JSGlobalContextCreateInGroup(contextGroup, jsClass);
+            CHECK(context, "ctx creation");
+
+            JSStringRef jsScriptString = JSStringCreateWithUTF8CString(scriptString.c_str());
+            CHECK(jsScriptString, "script to jsString");
+
+            JSValueRef jsScript = JSEvaluateScript(context, jsScriptString, nullptr, nullptr, 0, nullptr);
+            CHECK(jsScript, "script eval");
+            JSStringRelease(jsScriptString);
+
+            JSGlobalContextRelease(context);
+            JSContextGroupRelease(contextGroup);
+            JSClassRelease(jsClass);
+        }
+
+        return ret;
+    };
+    for (int t = 0; t < 8; ++t)
+        threadsList().push_back(std::thread(task));
+}
+
+int finalizeMultithreadedMultiVMExecutionTest()
+{
+    auto& threads = threadsList();
+    for (auto& thread : threads)
+        thread.join();
+
+    if (failuresFound)
+        printf("FAILED MultithreadedMultiVMExecutionTest\n");
+    return (failuresFound > 0);
+}
diff --git a/Source/JavaScriptCore/API/tests/MultithreadedMultiVMExecutionTest.h b/Source/JavaScriptCore/API/tests/MultithreadedMultiVMExecutionTest.h
new file mode 100644 (file)
index 0000000..6498b67
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void startMultithreadedMultiVMExecutionTest();
+
+/* Returns 1 if failures were encountered.  Else, returns 0. */
+extern int finalizeMultithreadedMultiVMExecutionTest();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
index 16b7418..036b554 100644 (file)
@@ -47,6 +47,7 @@
 #include "FunctionOverridesTest.h"
 #include "GlobalContextWithFinalizerTest.h"
 #include "JSONParseTest.h"
+#include "MultithreadedMultiVMExecutionTest.h"
 #include "PingPongStackOverflowTest.h"
 #include "TypedArrayCTest.h"
 
@@ -1190,6 +1191,7 @@ int main(int argc, char* argv[])
 #endif
 
     testCompareAndSwap();
+    startMultithreadedMultiVMExecutionTest();
 
 #if JSC_OBJC_API_ENABLED
     testObjectiveCAPI();
@@ -2008,6 +2010,8 @@ int main(int argc, char* argv[])
     globalObjectSetPrototypeTest();
     globalObjectPrivatePropertyTest();
 
+    failed = finalizeMultithreadedMultiVMExecutionTest() || failed;
+
     if (failed) {
         printf("FAIL: Some tests failed.\n");
         return 1;
index 79b15a7..968b8d8 100644 (file)
@@ -1,3 +1,79 @@
+2017-05-04  Mark Lam  <mark.lam@apple.com>
+
+        NeverDestroyed<String>(ASCIILiteral(...)) is not thread safe.
+        https://bugs.webkit.org/show_bug.cgi?id=171586
+        <rdar://problem/31873190>
+
+        Reviewed by Yusuke Suzuki.
+
+        JavaScriptCore allows multiple VMs to be instantiated, and each of these should
+        be able to run concurrently on different threads.  There is code in the VM that
+        allocates NeverDestroyed<String>(ASCIILiteral(...)) to defined immortal strings
+        meant to be shared by all VMs.
+
+        However, NeverDestroyed<String>(ASCIILiteral(...)) is not thread-safe because
+        each thread will ref and deref the underlying StringImpl.  Since this ref and
+        deref is not done in a thread-safe way, the NeverDestroyed<String> may get
+        destroyed due to the ref/deref races.  Additionally, each thread may modify the
+        StringImpl by setting its hash and also twiddling its flags.
+
+        The fix is to use the StaticStringImpl class which is safe for ref/derefing
+        concurrently from different threads.  StaticStringImpl is also pre-set with a
+        hash on construction, and its flags are set in such a way as to prevent twiddling
+        at runtime.  Hence, we will be able to share a NeverDestroyed<String> between
+        VMs, as long as it is backed by a StaticStringImpl.
+
+        An alternative solution would be to change all the uses of NeverDestroyed<String>
+        to use per-VM strings.  However, this solution is cumbersome, and makes it harder
+        to allocate the intended shared string.  It also uses more memory and takes more
+        CPU time because it requires allocating the same string for each VM instance.
+        The StaticStringImpl solution wins out because it is more efficient and is easier
+        to use.
+
+        The StaticStringImpl solution also can be used in WTF without a layer violation.
+        See Source/WTF/wtf/text/icu/TextBreakIteratorICU.h for an example.
+
+        Also added the MultithreadedMultiVMExecutionTest which runs multiple VMs in
+        multiple threads, all banging on the BuiltinExecutable's baseConstructorCode
+        NeverDestroyed<String>.  The test will manifest the issue reliably (before this
+        fix) if run on an ASAN build.
+
+        * API/tests/MultithreadedMultiVMExecutionTest.cpp: Added.
+        (threadsList):
+        (startMultithreadedMultiVMExecutionTest):
+        (finalizeMultithreadedMultiVMExecutionTest):
+        * API/tests/MultithreadedMultiVMExecutionTest.h: Added.
+        * API/tests/testapi.c:
+        (main):
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * builtins/BuiltinExecutables.cpp:
+        (JSC::BuiltinExecutables::createDefaultConstructor):
+        * inspector/agents/InspectorDebuggerAgent.cpp:
+        (Inspector::objectGroupForBreakpointAction):
+        * replay/scripts/CodeGeneratorReplayInputsTemplates.py:
+        * replay/scripts/tests/expected/generate-enum-encoding-helpers-with-guarded-values.json-TestReplayInputs.cpp:
+        (JSC::InputTraits<Test::SavedMouseButton>::type):
+        * replay/scripts/tests/expected/generate-enum-encoding-helpers.json-TestReplayInputs.cpp:
+        (JSC::InputTraits<Test::SavedMouseButton>::type):
+        * replay/scripts/tests/expected/generate-enum-with-guard.json-TestReplayInputs.cpp:
+        (JSC::InputTraits<Test::HandleWheelEvent>::type):
+        * replay/scripts/tests/expected/generate-enums-with-same-base-name.json-TestReplayInputs.cpp:
+        (JSC::InputTraits<Test::FormCombo>::type):
+        * replay/scripts/tests/expected/generate-input-with-guard.json-TestReplayInputs.cpp:
+        (JSC::InputTraits<Test::GetCurrentTime>::type):
+        (JSC::InputTraits<Test::SetRandomSeed>::type):
+        * replay/scripts/tests/expected/generate-input-with-vector-members.json-TestReplayInputs.cpp:
+        (JSC::InputTraits<Test::ArrayOfThings>::type):
+        (JSC::InputTraits<Test::SavedHistory>::type):
+        * replay/scripts/tests/expected/generate-inputs-with-flags.json-TestReplayInputs.cpp:
+        (JSC::InputTraits<Test::ScalarInput1>::type):
+        (JSC::InputTraits<Test::ScalarInput2>::type):
+        * replay/scripts/tests/expected/generate-memoized-type-modes.json-TestReplayInputs.cpp:
+        (JSC::InputTraits<Test::ScalarInput>::type):
+        (JSC::InputTraits<Test::MapInput>::type):
+        * runtime/IntlObject.cpp:
+        (JSC::numberingSystemsForLocale):
+
 2017-05-04  Sam Weinig  <sam@webkit.org>
 
         Remove support for legacy Notifications
index 7cb6c50..8ad9c44 100644 (file)
                FED94F2E171E3E2300BE77A4 /* Watchdog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */; };
                FED94F2F171E3E2300BE77A4 /* Watchdog.h in Headers */ = {isa = PBXBuildFile; fileRef = FED94F2C171E3E2300BE77A4 /* Watchdog.h */; settings = {ATTRIBUTES = (Private, ); }; };
                FEF040511AAE662D00BD28B0 /* CompareAndSwapTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */; };
+               FEF49AAB1EB9484B00653BDB /* MultithreadedMultiVMExecutionTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF49AA91EB947FE00653BDB /* MultithreadedMultiVMExecutionTest.cpp */; };
                FEFD6FC61D5E7992008F2F0B /* JSStringInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
 /* End PBXBuildFile section */
 
                FEDA50D51B97F4D9009A3B4F /* PingPongStackOverflowTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PingPongStackOverflowTest.h; path = API/tests/PingPongStackOverflowTest.h; sourceTree = "<group>"; };
                FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompareAndSwapTest.cpp; path = API/tests/CompareAndSwapTest.cpp; sourceTree = "<group>"; };
                FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompareAndSwapTest.h; path = API/tests/CompareAndSwapTest.h; sourceTree = "<group>"; };
+               FEF49AA91EB947FE00653BDB /* MultithreadedMultiVMExecutionTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MultithreadedMultiVMExecutionTest.cpp; path = API/tests/MultithreadedMultiVMExecutionTest.cpp; sourceTree = "<group>"; };
+               FEF49AAA1EB947FE00653BDB /* MultithreadedMultiVMExecutionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MultithreadedMultiVMExecutionTest.h; path = API/tests/MultithreadedMultiVMExecutionTest.h; sourceTree = "<group>"; };
                FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringInlines.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
                                C2181FC118A948FB0025A235 /* JSExportTests.mm */,
                                5C4E8E941DBEBDA20036F1FC /* JSONParseTest.cpp */,
                                5C4E8E951DBEBDA20036F1FC /* JSONParseTest.h */,
+                               FEF49AA91EB947FE00653BDB /* MultithreadedMultiVMExecutionTest.cpp */,
+                               FEF49AAA1EB947FE00653BDB /* MultithreadedMultiVMExecutionTest.h */,
                                144005170A531CB50005F061 /* minidom */,
                                FEDA50D41B97F442009A3B4F /* PingPongStackOverflowTest.cpp */,
                                FEDA50D51B97F4D9009A3B4F /* PingPongStackOverflowTest.h */,
                                FE0D4A061AB8DD0A002F54BF /* ExecutionTimeLimitTest.cpp in Sources */,
                                FECB8B271D25BB85006F2463 /* FunctionOverridesTest.cpp in Sources */,
                                FE0D4A091ABA2437002F54BF /* GlobalContextWithFinalizerTest.cpp in Sources */,
+                               FEF49AAB1EB9484B00653BDB /* MultithreadedMultiVMExecutionTest.cpp in Sources */,
                                C2181FC218A948FB0025A235 /* JSExportTests.mm in Sources */,
                                5C4E8E961DBEBE620036F1FC /* JSONParseTest.cpp in Sources */,
                                FE7C41961B97FC4B00F4D598 /* PingPongStackOverflowTest.cpp in Sources */,
index a5be5c9..9e0d461 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -44,8 +44,8 @@ BuiltinExecutables::BuiltinExecutables(VM& vm)
 
 UnlinkedFunctionExecutable* BuiltinExecutables::createDefaultConstructor(ConstructorKind constructorKind, const Identifier& name)
 {
-    static NeverDestroyed<const String> baseConstructorCode(ASCIILiteral("(function () { })"));
-    static NeverDestroyed<const String> derivedConstructorCode(ASCIILiteral("(function (...args) { super(...args); })"));
+    static NeverDestroyed<const String> baseConstructorCode(MAKE_STATIC_STRING_IMPL("(function () { })"));
+    static NeverDestroyed<const String> derivedConstructorCode(MAKE_STATIC_STRING_IMPL("(function (...args) { super(...args); })"));
 
     switch (constructorKind) {
     case ConstructorKind::None:
index 617efb9..754e66d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010, 2013, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2010, 2011 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -56,7 +56,7 @@ const char* InspectorDebuggerAgent::backtraceObjectGroup = "backtrace";
 // create objects in the same group.
 static String objectGroupForBreakpointAction(const ScriptBreakpointAction& action)
 {
-    static NeverDestroyed<String> objectGroup(ASCIILiteral("breakpoint-action-"));
+    static NeverDestroyed<String> objectGroup(MAKE_STATIC_STRING_IMPL("breakpoint-action-"));
     return makeString(objectGroup.get(), String::number(action.identifier));
 }
 
index 953e67f..9c11b2d 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # Copyright (c) 2011 Google Inc. All rights reserved.
 # Copyright (c) 2012 Intel Corporation. All rights reserved.
-# Copyright (c) 2013, 2014, 2016 Apple Inc. All rights reserved.
+# Copyright (c) 2013-2017 Apple Inc. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are
@@ -150,7 +150,7 @@ ${enumerableTypeTraitImplementations}
     InputTraitsImplementation = (
     """const String& InputTraits<${qualifiedInputName}>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral(${inputNameStringLiteral}));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL(${inputNameStringLiteral}));
     return type;
 }
 
index d5b1585..22271ff 100644 (file)
@@ -50,7 +50,7 @@ SavedMouseButton::~SavedMouseButton()
 namespace JSC {
 const String& InputTraits<Test::SavedMouseButton>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral("SavedMouseButton"));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL("SavedMouseButton"));
     return type;
 }
 
index 4ed407c..1f68b6c 100644 (file)
@@ -51,7 +51,7 @@ SavedMouseButton::~SavedMouseButton()
 namespace JSC {
 const String& InputTraits<Test::SavedMouseButton>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral("SavedMouseButton"));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL("SavedMouseButton"));
     return type;
 }
 
index 486756e..c86d236 100644 (file)
@@ -52,7 +52,7 @@ HandleWheelEvent::~HandleWheelEvent()
 namespace JSC {
 const String& InputTraits<Test::HandleWheelEvent>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral("HandleWheelEvent"));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL("HandleWheelEvent"));
     return type;
 }
 
index a19644f..559aed1 100644 (file)
@@ -52,7 +52,7 @@ FormCombo::~FormCombo()
 namespace JSC {
 const String& InputTraits<Test::FormCombo>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral("FormCombo"));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL("FormCombo"));
     return type;
 }
 
index 9cbb7af..002f3e9 100644 (file)
@@ -62,7 +62,7 @@ namespace JSC {
 #if ENABLE(DUMMY_FEATURE)
 const String& InputTraits<Test::GetCurrentTime>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral("GetCurrentTime"));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL("GetCurrentTime"));
     return type;
 }
 
@@ -84,7 +84,7 @@ bool InputTraits<Test::GetCurrentTime>::decode(EncodedValue& encodedValue, std::
 
 const String& InputTraits<Test::SetRandomSeed>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral("SetRandomSeed"));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL("SetRandomSeed"));
     return type;
 }
 
index f2f962a..7b9b4c8 100644 (file)
@@ -63,7 +63,7 @@ SavedHistory::~SavedHistory()
 namespace JSC {
 const String& InputTraits<Test::ArrayOfThings>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral("ArrayOfThings"));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL("ArrayOfThings"));
     return type;
 }
 
@@ -94,7 +94,7 @@ bool InputTraits<Test::ArrayOfThings>::decode(EncodedValue& encodedValue, std::u
 
 const String& InputTraits<Test::SavedHistory>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral("SavedHistory"));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL("SavedHistory"));
     return type;
 }
 
index 821f4d0..d1cd9c3 100644 (file)
@@ -59,7 +59,7 @@ ScalarInput2::~ScalarInput2()
 namespace JSC {
 const String& InputTraits<Test::ScalarInput1>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral("ScalarInput1"));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL("ScalarInput1"));
     return type;
 }
 
@@ -80,7 +80,7 @@ bool InputTraits<Test::ScalarInput1>::decode(EncodedValue& encodedValue, std::un
 
 const String& InputTraits<Test::ScalarInput2>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral("ScalarInput2"));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL("ScalarInput2"));
     return type;
 }
 
index b67a9e9..45b1462 100644 (file)
@@ -59,7 +59,7 @@ MapInput::~MapInput()
 namespace JSC {
 const String& InputTraits<Test::ScalarInput>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral("ScalarInput"));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL("ScalarInput"));
     return type;
 }
 
@@ -80,7 +80,7 @@ bool InputTraits<Test::ScalarInput>::decode(EncodedValue& encodedValue, std::uni
 
 const String& InputTraits<Test::MapInput>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral("MapInput"));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL("MapInput"));
     return type;
 }
 
index 83059a1..ce8d147 100644 (file)
@@ -853,18 +853,23 @@ Vector<String> numberingSystemsForLocale(const String& locale)
 {
     static NeverDestroyed<Vector<String>> cachedNumberingSystems;
     Vector<String>& availableNumberingSystems = cachedNumberingSystems.get();
-    if (availableNumberingSystems.isEmpty()) {
-        UErrorCode status = U_ZERO_ERROR;
-        UEnumeration* numberingSystemNames = unumsys_openAvailableNames(&status);
-        ASSERT(U_SUCCESS(status));
-
-        int32_t resultLength;
-        // Numbering system names are always ASCII, so use char[].
-        while (const char* result = uenum_next(numberingSystemNames, &resultLength, &status)) {
+
+    if (UNLIKELY(availableNumberingSystems.isEmpty())) {
+        static StaticLock cachedNumberingSystemsMutex;
+        std::lock_guard<StaticLock> lock(cachedNumberingSystemsMutex);
+        if (availableNumberingSystems.isEmpty()) {
+            UErrorCode status = U_ZERO_ERROR;
+            UEnumeration* numberingSystemNames = unumsys_openAvailableNames(&status);
             ASSERT(U_SUCCESS(status));
-            availableNumberingSystems.append(String(result, resultLength));
+
+            int32_t resultLength;
+            // Numbering system names are always ASCII, so use char[].
+            while (const char* result = uenum_next(numberingSystemNames, &resultLength, &status)) {
+                ASSERT(U_SUCCESS(status));
+                availableNumberingSystems.append(String(result, resultLength));
+            }
+            uenum_close(numberingSystemNames);
         }
-        uenum_close(numberingSystemNames);
     }
 
     UErrorCode status = U_ZERO_ERROR;
index d2de4f0..a8b66c9 100644 (file)
@@ -1,3 +1,48 @@
+2017-05-04  Mark Lam  <mark.lam@apple.com>
+
+        NeverDestroyed<String>(ASCIILiteral(...)) is not thread safe.
+        https://bugs.webkit.org/show_bug.cgi?id=171586
+        <rdar://problem/31873190>
+
+        Reviewed by Yusuke Suzuki.
+
+        StaticStringImpl is meant to be thread-safe.  However, it has a bug: it did not
+        set the s_hashFlagDidReportCost flag.  As a result, if cost() is called on it,
+        different threads may try to change its flags bits at the same time.  This patch
+        changes StaticStringImpl to always set the s_hashFlagDidReportCost flag.
+
+        Also factored out StringImplShape and made StringImpl and StaticStringImpl extend
+        it.  This makes it more clear that the 2 are intended to have the same shape.
+        Note: there is already a static_assert that the 2 have the same size.  This
+        change also ensures that they both have the same shape, which is a requirement in
+        order for StaticStringImpl to work.
+
+        Introduced the MAKE_STATIC_STRING_IMPL macro as a convenient way to instantiate
+        StaticStringImpls from literal strings.  This allows us to trivially change
+
+            NeverDestroyed<String> myString(ASCIILiteral("myString"));
+
+        to ...
+
+            NeverDestroyed<String> myString(MAKE_STATIC_STRING_IMPL("myString"));
+
+        and by so doing, make it thread-safe.
+
+        MAKE_STATIC_STRING_IMPL instantiates a lambda function to create the static
+        StaticStringImpls.
+
+        * wtf/text/StringImpl.h:
+        (WTF::StringImplShape::StringImplShape):
+        (WTF::StringImpl::StringImpl):
+        (WTF::StringImpl::cost):
+        (WTF::StringImpl::setHash):
+        (WTF::StringImpl::StaticStringImpl::StaticStringImpl):
+        (WTF::StringImpl::StaticStringImpl::operator StringImpl&):
+        * wtf/text/WTFString.h:
+        (WTF::String::String):
+        * wtf/text/icu/TextBreakIteratorICU.h:
+        (WTF::caretRules):
+
 2017-05-04  Sam Weinig  <sam@webkit.org>
 
         Remove support for legacy Notifications
index ee93867..de9a771 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2005-2010, 2013-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2005-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2009 Google Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
@@ -129,7 +129,49 @@ struct StringStats {
 #define STRING_STATS_DEREF_STRING(string) ((void)0)
 #endif
 
-class StringImpl {
+class StringImplShape {
+    WTF_MAKE_NONCOPYABLE(StringImplShape);
+protected:
+    StringImplShape(unsigned refCount, unsigned length, const LChar* data8, unsigned hashAndFlags)
+        : m_refCount(refCount)
+        , m_length(length)
+        , m_data8(data8)
+        , m_hashAndFlags(hashAndFlags)
+    { }
+
+    StringImplShape(unsigned refCount, unsigned length, const UChar* data16, unsigned hashAndFlags)
+        : m_refCount(refCount)
+        , m_length(length)
+        , m_data16(data16)
+        , m_hashAndFlags(hashAndFlags)
+    { }
+
+    template<unsigned charactersCount>
+    constexpr StringImplShape(unsigned refCount, unsigned length, const char (&characters)[charactersCount], unsigned hashAndFlags)
+        : m_refCount(refCount)
+        , m_length(length)
+        , m_data8(reinterpret_cast<const LChar*>(characters))
+        , m_hashAndFlags(hashAndFlags)
+    { }
+    
+    template<unsigned charactersCount>
+    constexpr StringImplShape(unsigned refCount, unsigned length, const char16_t (&characters)[charactersCount], unsigned hashAndFlags)
+        : m_refCount(refCount)
+        , m_length(length)
+        , m_data16(reinterpret_cast<const UChar*>(characters))
+        , m_hashAndFlags(hashAndFlags)
+    { }
+
+    unsigned m_refCount;
+    unsigned m_length;
+    union {
+        const LChar* m_data8;
+        const UChar* m_data16;
+    };
+    mutable unsigned m_hashAndFlags;
+};
+
+class StringImpl : private StringImplShape {
     WTF_MAKE_NONCOPYABLE(StringImpl); WTF_MAKE_FAST_ALLOCATED;
     friend struct WTF::CStringTranslator;
     template<typename CharacterType> friend struct WTF::HashAndCharactersTranslator;
@@ -174,10 +216,7 @@ private:
     enum Force8Bit { Force8BitConstructor };
     // Create a normal 8-bit string with internal storage (BufferInternal)
     StringImpl(unsigned length, Force8Bit)
-        : m_refCount(s_refCountIncrement)
-        , m_length(length)
-        , m_data8(tailPointer<LChar>())
-        , m_hashAndFlags(s_hashFlag8BitBuffer | StringNormal | BufferInternal)
+        : StringImplShape(s_refCountIncrement, length, tailPointer<LChar>(), s_hashFlag8BitBuffer | StringNormal | BufferInternal)
     {
         ASSERT(m_data8);
         ASSERT(m_length);
@@ -187,10 +226,7 @@ private:
 
     // Create a normal 16-bit string with internal storage (BufferInternal)
     StringImpl(unsigned length)
-        : m_refCount(s_refCountIncrement)
-        , m_length(length)
-        , m_data16(tailPointer<UChar>())
-        , m_hashAndFlags(StringNormal | BufferInternal)
+        : StringImplShape(s_refCountIncrement, length, tailPointer<UChar>(), StringNormal | BufferInternal)
     {
         ASSERT(m_data16);
         ASSERT(m_length);
@@ -200,10 +236,7 @@ private:
 
     // Create a StringImpl adopting ownership of the provided buffer (BufferOwned)
     StringImpl(MallocPtr<LChar> characters, unsigned length)
-        : m_refCount(s_refCountIncrement)
-        , m_length(length)
-        , m_data8(characters.leakPtr())
-        , m_hashAndFlags(s_hashFlag8BitBuffer | StringNormal | BufferOwned)
+        : StringImplShape(s_refCountIncrement, length, characters.leakPtr(), s_hashFlag8BitBuffer | StringNormal | BufferOwned)
     {
         ASSERT(m_data8);
         ASSERT(m_length);
@@ -213,10 +246,7 @@ private:
 
     enum ConstructWithoutCopyingTag { ConstructWithoutCopying };
     StringImpl(const UChar* characters, unsigned length, ConstructWithoutCopyingTag)
-        : m_refCount(s_refCountIncrement)
-        , m_length(length)
-        , m_data16(characters)
-        , m_hashAndFlags(StringNormal | BufferInternal)
+        : StringImplShape(s_refCountIncrement, length, characters, StringNormal | BufferInternal)
     {
         ASSERT(m_data16);
         ASSERT(m_length);
@@ -225,10 +255,7 @@ private:
     }
 
     StringImpl(const LChar* characters, unsigned length, ConstructWithoutCopyingTag)
-        : m_refCount(s_refCountIncrement)
-        , m_length(length)
-        , m_data8(characters)
-        , m_hashAndFlags(s_hashFlag8BitBuffer | StringNormal | BufferInternal)
+        : StringImplShape(s_refCountIncrement, length, characters, s_hashFlag8BitBuffer | StringNormal | BufferInternal)
     {
         ASSERT(m_data8);
         ASSERT(m_length);
@@ -238,10 +265,7 @@ private:
 
     // Create a StringImpl adopting ownership of the provided buffer (BufferOwned)
     StringImpl(MallocPtr<UChar> characters, unsigned length)
-        : m_refCount(s_refCountIncrement)
-        , m_length(length)
-        , m_data16(characters.leakPtr())
-        , m_hashAndFlags(StringNormal | BufferOwned)
+        : StringImplShape(s_refCountIncrement, length, characters.leakPtr(), StringNormal | BufferOwned)
     {
         ASSERT(m_data16);
         ASSERT(m_length);
@@ -251,10 +275,7 @@ private:
 
     // Used to create new strings that are a substring of an existing 8-bit StringImpl (BufferSubstring)
     StringImpl(const LChar* characters, unsigned length, Ref<StringImpl>&& base)
-        : m_refCount(s_refCountIncrement)
-        , m_length(length)
-        , m_data8(characters)
-        , m_hashAndFlags(s_hashFlag8BitBuffer | StringNormal | BufferSubstring)
+        : StringImplShape(s_refCountIncrement, length, characters, s_hashFlag8BitBuffer | StringNormal | BufferSubstring)
     {
         ASSERT(is8Bit());
         ASSERT(m_data8);
@@ -268,10 +289,7 @@ private:
 
     // Used to create new strings that are a substring of an existing 16-bit StringImpl (BufferSubstring)
     StringImpl(const UChar* characters, unsigned length, Ref<StringImpl>&& base)
-        : m_refCount(s_refCountIncrement)
-        , m_length(length)
-        , m_data16(characters)
-        , m_hashAndFlags(StringNormal | BufferSubstring)
+        : StringImplShape(s_refCountIncrement, length, characters, StringNormal | BufferSubstring)
     {
         ASSERT(!is8Bit());
         ASSERT(m_data16);
@@ -399,6 +417,10 @@ public:
         if (bufferOwnership() == BufferSubstring)
             return substringBuffer()->cost();
 
+        // Note: we must not alter the m_hashAndFlags field in instances of StaticStringImpl.
+        // We ensure this by pre-setting the s_hashFlagDidReportCost bit in all instances of
+        // StaticStringImpl. As a result, StaticStringImpl instances will always return a cost of
+        // 0 here and avoid modifying m_hashAndFlags.
         if (m_hashAndFlags & s_hashFlagDidReportCost)
             return 0;
 
@@ -460,6 +482,7 @@ private:
     void setHash(unsigned hash) const
     {
         ASSERT(!hasHash());
+        ASSERT(!isStatic());
         // Multiple clients assume that StringHasher is the canonical string hash function.
         ASSERT(hash == (is8Bit() ? StringHasher::computeHashAndMaskTop8Bits(m_data8, m_length) : StringHasher::computeHashAndMaskTop8Bits(m_data16, m_length)));
         ASSERT(!(hash & (s_flagMask << (8 * sizeof(hash) - s_flagCount)))); // Verify that enough high bits are empty.
@@ -537,27 +560,47 @@ public:
         m_refCount = tempRefCount;
     }
 
-    class StaticStringImpl {
+    class StaticStringImpl : private StringImplShape {
         WTF_MAKE_NONCOPYABLE(StaticStringImpl);
     public:
         // Used to construct static strings, which have an special refCount that can never hit zero.
         // This means that the static string will never be destroyed, which is important because
         // static strings will be shared across threads & ref-counted in a non-threadsafe manner.
+        //
+        // In order to make StaticStringImpl thread safe, we also need to ensure that the rest of
+        // the fields are never mutated by threads. We have this guarantee because:
+        //
+        // 1. m_length is only set on construction and never mutated thereafter.
+        //
+        // 2. m_data8 and m_data16 are only set on construction and never mutated thereafter.
+        //    We also know that a StringImpl never changes from 8 bit to 16 bit because there
+        //    is no way to set/clear the s_hashFlag8BitBuffer flag other than at construction.
+        //
+        // 3. m_hashAndFlags will not be mutated by different threads because:
+        //
+        //    a. StaticStringImpl's constructor sets the s_hashFlagDidReportCost flag to ensure
+        //       that StringImpl::cost() returns early.
+        //       This means StaticStringImpl costs are not counted. But since there should only
+        //       be a finite set of StaticStringImpls, their cost can be aggregated into a single
+        //       system cost if needed.
+        //    b. setIsAtomic() is never called on a StaticStringImpl.
+        //       setIsAtomic() asserts !isStatic().
+        //    c. setHash() is never called on a StaticStringImpl.
+        //       StaticStringImpl's constructor sets the hash on construction.
+        //       StringImpl::hash() only sets a new hash iff !hasHash().
+        //       Additionally, StringImpl::setHash() asserts hasHash() and !isStatic().
+
         template<unsigned charactersCount>
         constexpr StaticStringImpl(const char (&characters)[charactersCount], StringKind stringKind = StringNormal)
-            : m_refCount(s_refCountFlagIsStaticString)
-            , m_length(charactersCount - 1)
-            , m_data8(characters)
-            , m_hashAndFlags(s_hashFlag8BitBuffer | stringKind | BufferInternal | (StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount))
+            : StringImplShape(s_refCountFlagIsStaticString, charactersCount - 1, characters,
+                s_hashFlag8BitBuffer | s_hashFlagDidReportCost | stringKind | BufferInternal | (StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount))
         {
         }
 
         template<unsigned charactersCount>
         constexpr StaticStringImpl(const char16_t (&characters)[charactersCount], StringKind stringKind = StringNormal)
-            : m_refCount(s_refCountFlagIsStaticString)
-            , m_length(charactersCount - 1)
-            , m_data16(characters)
-            , m_hashAndFlags(stringKind | BufferInternal | (StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount))
+            : StringImplShape(s_refCountFlagIsStaticString, charactersCount - 1, characters,
+                s_hashFlagDidReportCost | stringKind | BufferInternal | (StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount))
         {
         }
 
@@ -565,15 +608,6 @@ public:
         {
             return *reinterpret_cast<StringImpl*>(this);
         }
-
-        // These member variables must match the layout of StringImpl.
-        unsigned m_refCount;
-        unsigned m_length;
-        union {
-            const char* m_data8;
-            const char16_t* m_data16;
-        };
-        unsigned m_hashAndFlags;
     };
 
     WTF_EXPORTDATA static StaticStringImpl s_atomicEmptyString;
@@ -739,10 +773,7 @@ protected:
 
     // Used to create new symbol strings that holds existing 8-bit [[Description]] string as a substring buffer (BufferSubstring).
     StringImpl(CreateSymbolTag, const LChar* characters, unsigned length)
-        : m_refCount(s_refCountIncrement)
-        , m_length(length)
-        , m_data8(characters)
-        , m_hashAndFlags(s_hashFlag8BitBuffer | StringSymbol | BufferSubstring)
+        : StringImplShape(s_refCountIncrement, length, characters, s_hashFlag8BitBuffer | StringSymbol | BufferSubstring)
     {
         ASSERT(is8Bit());
         ASSERT(m_data8);
@@ -751,10 +782,7 @@ protected:
 
     // Used to create new symbol strings that holds existing 16-bit [[Description]] string as a substring buffer (BufferSubstring).
     StringImpl(CreateSymbolTag, const UChar* characters, unsigned length)
-        : m_refCount(s_refCountIncrement)
-        , m_length(length)
-        , m_data16(characters)
-        , m_hashAndFlags(StringSymbol | BufferSubstring)
+        : StringImplShape(s_refCountIncrement, length, characters, StringSymbol | BufferSubstring)
     {
         ASSERT(!is8Bit());
         ASSERT(m_data16);
@@ -763,10 +791,7 @@ protected:
 
     // Null symbol.
     StringImpl(CreateSymbolTag)
-        : m_refCount(s_refCountIncrement)
-        , m_length(0)
-        , m_data8(empty()->characters8())
-        , m_hashAndFlags(s_hashFlag8BitBuffer | StringSymbol | BufferSubstring)
+        : StringImplShape(s_refCountIncrement, 0, empty()->characters8(), s_hashFlag8BitBuffer | StringSymbol | BufferSubstring)
     {
         ASSERT(is8Bit());
         ASSERT(m_data8);
@@ -859,19 +884,11 @@ public:
         ASSERT(existingHash() == StringHasher::computeHashAndMaskTop8Bits(characters8(), length()));
     }
 #endif
-
-private:
-    // These member variables must match the layout of StaticStringImpl.
-    unsigned m_refCount;
-    unsigned m_length;
-    union {
-        const LChar* m_data8;
-        const UChar* m_data16;
-    };
-    mutable unsigned m_hashAndFlags;
 };
 
-static_assert(sizeof(StringImpl) == sizeof(StringImpl::StaticStringImpl), "");
+using StaticStringImpl = StringImpl::StaticStringImpl;
+
+static_assert(sizeof(StringImpl) == sizeof(StaticStringImpl), "");
 
 #if !ASSERT_DISABLED
 // StringImpls created from StaticStringImpl will ASSERT
@@ -1136,9 +1153,16 @@ template<unsigned length> inline bool equalLettersIgnoringASCIICase(const String
     return string && equalLettersIgnoringASCIICase(*string, lowercaseLetters);
 }
 
+#define MAKE_STATIC_STRING_IMPL(characters) ([] { \
+        static StaticStringImpl impl(characters); \
+        return &impl; \
+    }())
+
+
 } // namespace WTF
 
 using WTF::StringImpl;
+using WTF::StaticStringImpl;
 using WTF::equal;
 using WTF::TextCaseSensitivity;
 using WTF::TextCaseSensitive;
index 30b375e..6a2406c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2004-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -114,8 +114,11 @@ public:
     String(Ref<AtomicStringImpl>&&);
     String(RefPtr<AtomicStringImpl>&&);
 
+    String(StaticStringImpl&);
+    String(StaticStringImpl*);
+
     // Construct a string from a constant string literal.
-    WTF_EXPORT_STRING_API String(ASCIILiteral characters);
+    WTF_EXPORT_STRING_API String(ASCIILiteral);
 
     // Construct a string from a constant string literal.
     // This constructor is the "big" version, as it put the length in the function call and generate bigger code.
@@ -489,6 +492,8 @@ private:
     RefPtr<StringImpl> m_impl;
 };
 
+static_assert(sizeof(String) == sizeof(void*), "String should effectively be a pointer to a StringImpl, and efficient to pass by value");
+
 inline bool operator==(const String& a, const String& b) { return equal(a.impl(), b.impl()); }
 inline bool operator==(const String& a, const LChar* b) { return equal(a.impl(), b); }
 inline bool operator==(const String& a, const char* b) { return equal(a.impl(), reinterpret_cast<const LChar*>(b)); }
@@ -558,6 +563,16 @@ inline String::String(RefPtr<AtomicStringImpl>&& impl)
 {
 }
 
+inline String::String(StaticStringImpl& impl)
+    : m_impl(reinterpret_cast<StringImpl*>(&impl))
+{
+}
+
+inline String::String(StaticStringImpl* impl)
+    : m_impl(reinterpret_cast<StringImpl*>(impl))
+{
+}
+
 template<size_t inlineCapacity, typename OverflowHandler>
 String::String(const Vector<UChar, inlineCapacity, OverflowHandler>& vector)
     : m_impl(vector.size() ? StringImpl::create(vector.data(), vector.size()) : Ref<StringImpl>(*StringImpl::empty()))
@@ -728,7 +743,7 @@ template<> struct IntegerToStringConversionTrait<String> {
     static String flush(LChar* characters, unsigned length, void*) { return { characters, length }; }
 };
 
-}
+} // namespace WTF
 
 using WTF::CString;
 using WTF::KeepTrailingZeros;
index 0b17fa8..308e40e 100644 (file)
@@ -31,7 +31,7 @@ namespace WTF {
 #if USE_ICU_CARET_ITERATOR
 static String caretRules()
 {
-    return ASCIILiteral(
+    static StaticStringImpl caretRuleString(
         // This rule set is based on character-break iterator rules of ICU 57
         // <http://source.icu-project.org/repos/icu/icu/tags/release-57-1/source/data/brkitr/>.
         // The major differences from the original ones are listed below:
@@ -128,6 +128,7 @@ static String caretRules()
         "$RI $RI+;"
         "$EmojiForMods [$EmojiVar $EmojiMods]+;"
     );
+    return caretRuleString;
 }
 #endif
 
index 5d19b10..f285f55 100644 (file)
@@ -1,3 +1,130 @@
+2017-05-04  Mark Lam  <mark.lam@apple.com>
+
+        NeverDestroyed<String>(ASCIILiteral(...)) is not thread safe.
+        https://bugs.webkit.org/show_bug.cgi?id=171586
+        <rdar://problem/31873190>
+
+        Reviewed by Yusuke Suzuki.
+
+        No new tests because we're just converting uses of ASCIILiteral (in the
+        instantiation of NeverDestroyed<String> and NeverDestroyed<const String>) to
+        MAKE_STATIC_STRING_IMPL.
+
+        The correctness of using MAKE_STATIC_STRING_IMPL is tested in the newly added
+        API test in this patch.
+
+        Also changed "static NeverDestroyed<ASCIILiteral>" instances in
+        SQLiteIDBBackingStore.cpp to "static const char* const" because they are only
+        ever used to get the underlying const char*.
+
+        * Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:
+        (WebCore::IDBServer::SQLiteIDBBackingStore::getRecord):
+        (WebCore::IDBServer::SQLiteIDBBackingStore::cachedStatementForGetAllObjectStoreRecords):
+        * Modules/mediastream/MediaEndpointSessionDescription.cpp:
+        * Modules/mediastream/RTCRtpTransceiver.cpp:
+        * Modules/mediastream/SDPProcessor.cpp:
+        * Modules/navigatorcontentutils/NavigatorContentUtils.cpp:
+        (WebCore::customHandlersStateString):
+        (WebCore::NavigatorContentUtils::isProtocolHandlerRegistered):
+        * Modules/speech/SpeechSynthesis.cpp:
+        (WebCore::SpeechSynthesis::boundaryEventOccurred):
+        * accessibility/AccessibilityMediaControls.cpp:
+        (WebCore::AccessibilityMediaControl::controlTypeName):
+        (WebCore::AccessibilityMediaControl::title):
+        (WebCore::AccessibilityMediaControlsContainer::elementTypeName):
+        (WebCore::AccessibilityMediaTimeline::helpText):
+        (WebCore::AccessibilityMediaTimeDisplay::accessibilityDescription):
+        * bindings/js/JSLazyEventListener.cpp:
+        (WebCore::eventParameterName):
+        * contentextensions/ContentExtensionsBackend.cpp:
+        (WebCore::ContentExtensions::ContentExtensionsBackend::displayNoneCSSRule):
+        * css/CSSDefaultStyleSheets.cpp:
+        (WebCore::screenEval):
+        (WebCore::printEval):
+        * css/MediaList.cpp:
+        (WebCore::addResolutionWarningMessageToConsole):
+        * css/StyleSheetContents.cpp:
+        (WebCore::StyleSheetContents::parseAuthorStyleSheet):
+        * dom/Document.cpp:
+        (WebCore::Document::readyState):
+        * dom/LoadableClassicScript.cpp:
+        (WebCore::LoadableClassicScript::notifyFinished):
+        * dom/PseudoElement.cpp:
+        (WebCore::PseudoElement::pseudoElementNameForEvents):
+        * editing/MarkupAccumulator.cpp:
+        (WebCore::MarkupAccumulator::shouldAddNamespaceElement):
+        * editing/cocoa/DataDetection.mm:
+        (WebCore::DataDetection::dataDetectorURLProtocol):
+        * editing/markup.cpp:
+        (WebCore::StyledMarkupAccumulator::styleNodeCloseTag):
+        (WebCore::createMarkupInternal):
+        * html/FormController.cpp:
+        (WebCore::formStateSignature):
+        * html/ImageInputType.cpp:
+        (WebCore::ImageInputType::appendFormData):
+        * html/canvas/CanvasRenderingContext2D.cpp:
+        (WebCore::CanvasRenderingContext2D::realizeSaves):
+        (WebCore::CanvasRenderingContext2D::getImageData):
+        * html/parser/XSSAuditor.cpp:
+        (WebCore::XSSAuditor::init):
+        (WebCore::XSSAuditor::eraseDangerousAttributesIfInjected):
+        * html/track/VTTCue.cpp:
+        (WebCore::startKeyword):
+        (WebCore::middleKeyword):
+        (WebCore::endKeyword):
+        (WebCore::leftKeyword):
+        (WebCore::rightKeyword):
+        (WebCore::verticalGrowingLeftKeyword):
+        (WebCore::verticalGrowingRightKeyword):
+        (WebCore::VTTCue::determineTextDirection):
+        (WebCore::VTTCue::markFutureAndPastNodes):
+        * inspector/InspectorCSSAgent.cpp:
+        (WebCore::computePseudoClassMask):
+        * inspector/InspectorIndexedDBAgent.cpp:
+        * inspector/InspectorPageAgent.cpp:
+        (WebCore::InspectorPageAgent::sourceMapURLForResource):
+        * inspector/PageDebuggerAgent.cpp:
+        (WebCore::PageDebuggerAgent::sourceMapURLForScript):
+        * loader/ImageLoader.cpp:
+        (WebCore::ImageLoader::notifyFinished):
+        * loader/TextTrackLoader.cpp:
+        (WebCore::TextTrackLoader::corsPolicyPreventedLoad):
+        * loader/icon/IconDatabase.cpp:
+        (WebCore::IconDatabase::defaultDatabaseFilename):
+        * page/CaptionUserPreferencesMediaAF.cpp:
+        (WebCore::CaptionUserPreferencesMediaAF::captionsTextEdgeCSS):
+        * page/SecurityOrigin.cpp:
+        (WebCore::SecurityOrigin::urlWithUniqueSecurityOrigin):
+        * page/UserContentURLPattern.cpp:
+        (WebCore::UserContentURLPattern::parse):
+        * platform/MIMETypeRegistry.cpp:
+        (WebCore::defaultMIMEType):
+        * platform/animation/Animation.cpp:
+        (WebCore::Animation::initialName):
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::engineDescription):
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::engineDescription):
+        * platform/graphics/cocoa/FontCacheCoreText.cpp:
+        (WebCore::FontCache::similarFont):
+        * platform/gtk/UserAgentGtk.cpp:
+        (WebCore::platformVersionForUAString):
+        * platform/mock/mediasource/MockBox.cpp:
+        (WebCore::MockTrackBox::type):
+        (WebCore::MockInitializationBox::type):
+        (WebCore::MockSampleBox::type):
+        * platform/network/HTTPHeaderValues.cpp:
+        (WebCore::HTTPHeaderValues::textPlainContentType):
+        (WebCore::HTTPHeaderValues::formURLEncodedContentType):
+        (WebCore::HTTPHeaderValues::noCache):
+        (WebCore::HTTPHeaderValues::maxAge0):
+        * platform/network/HTTPParsers.cpp:
+        (WebCore::parseXSSProtectionHeader):
+        * replay/MemoizedDOMResult.cpp:
+        (JSC::InputTraits<MemoizedDOMResultBase>::type):
+        * svg/SVGTransformValue.cpp:
+        (WebCore::SVGTransformValue::transformTypePrefixForParsing):
+
 2017-05-04  Jeremy Jones  <jeremyj@apple.com>
 
         Add muted to WebPlaybackSessionModel.
index 28664fe..ddabad4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -1899,15 +1899,15 @@ IDBError SQLiteIDBBackingStore::getRecord(const IDBResourceIdentifier& transacti
     int64_t recordID = 0;
     ThreadSafeDataBuffer resultBuffer;
     {
-        static NeverDestroyed<ASCIILiteral> lowerOpenUpperOpen("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
-        static NeverDestroyed<ASCIILiteral> lowerOpenUpperClosed("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
-        static NeverDestroyed<ASCIILiteral> lowerClosedUpperOpen("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
-        static NeverDestroyed<ASCIILiteral> lowerClosedUpperClosed("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
+        static const char* const lowerOpenUpperOpen = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
+        static const char* const lowerOpenUpperClosed = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
+        static const char* const lowerClosedUpperOpen = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
+        static const char* const lowerClosedUpperClosed = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
 
-        static NeverDestroyed<ASCIILiteral> lowerOpenUpperOpenKeyOnly("SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
-        static NeverDestroyed<ASCIILiteral> lowerOpenUpperClosedKeyOnly("SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
-        static NeverDestroyed<ASCIILiteral> lowerClosedUpperOpenKeyOnly("SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
-        static NeverDestroyed<ASCIILiteral> lowerClosedUpperClosedKeyOnly("SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
+        static const char* const lowerOpenUpperOpenKeyOnly = "SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
+        static const char* const lowerOpenUpperClosedKeyOnly = "SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
+        static const char* const lowerClosedUpperOpenKeyOnly = "SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
+        static const char* const lowerClosedUpperClosedKeyOnly = "SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
 
         SQLiteStatement* sql = nullptr;
 
@@ -1915,27 +1915,27 @@ IDBError SQLiteIDBBackingStore::getRecord(const IDBResourceIdentifier& transacti
         case IDBGetRecordDataType::KeyAndValue:
             if (keyRange.lowerOpen) {
                 if (keyRange.upperOpen)
-                    sql = cachedStatement(SQL::GetValueRecordsLowerOpenUpperOpen, lowerOpenUpperOpen.get());
+                    sql = cachedStatement(SQL::GetValueRecordsLowerOpenUpperOpen, lowerOpenUpperOpen);
                 else
-                    sql = cachedStatement(SQL::GetValueRecordsLowerOpenUpperClosed, lowerOpenUpperClosed.get());
+                    sql = cachedStatement(SQL::GetValueRecordsLowerOpenUpperClosed, lowerOpenUpperClosed);
             } else {
                 if (keyRange.upperOpen)
-                    sql = cachedStatement(SQL::GetValueRecordsLowerClosedUpperOpen, lowerClosedUpperOpen.get());
+                    sql = cachedStatement(SQL::GetValueRecordsLowerClosedUpperOpen, lowerClosedUpperOpen);
                 else
-                    sql = cachedStatement(SQL::GetValueRecordsLowerClosedUpperClosed, lowerClosedUpperClosed.get());
+                    sql = cachedStatement(SQL::GetValueRecordsLowerClosedUpperClosed, lowerClosedUpperClosed);
             }
             break;
         case IDBGetRecordDataType::KeyOnly:
             if (keyRange.lowerOpen) {
                 if (keyRange.upperOpen)
-                    sql = cachedStatement(SQL::GetKeyRecordsLowerOpenUpperOpen, lowerOpenUpperOpenKeyOnly.get());
+                    sql = cachedStatement(SQL::GetKeyRecordsLowerOpenUpperOpen, lowerOpenUpperOpenKeyOnly);
                 else
-                    sql = cachedStatement(SQL::GetKeyRecordsLowerOpenUpperClosed, lowerOpenUpperClosedKeyOnly.get());
+                    sql = cachedStatement(SQL::GetKeyRecordsLowerOpenUpperClosed, lowerOpenUpperClosedKeyOnly);
             } else {
                 if (keyRange.upperOpen)
-                    sql = cachedStatement(SQL::GetKeyRecordsLowerClosedUpperOpen, lowerClosedUpperOpenKeyOnly.get());
+                    sql = cachedStatement(SQL::GetKeyRecordsLowerClosedUpperOpen, lowerClosedUpperOpenKeyOnly);
                 else
-                    sql = cachedStatement(SQL::GetKeyRecordsLowerClosedUpperClosed, lowerClosedUpperClosedKeyOnly.get());
+                    sql = cachedStatement(SQL::GetKeyRecordsLowerClosedUpperClosed, lowerClosedUpperClosedKeyOnly);
             }
         }
 
@@ -2003,36 +2003,36 @@ IDBError SQLiteIDBBackingStore::getAllRecords(const IDBResourceIdentifier& trans
 
 SQLiteStatement* SQLiteIDBBackingStore::cachedStatementForGetAllObjectStoreRecords(const IDBGetAllRecordsData& getAllRecordsData)
 {
-    static NeverDestroyed<ASCIILiteral> lowerOpenUpperOpenKey("SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
-    static NeverDestroyed<ASCIILiteral> lowerOpenUpperClosedKey("SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
-    static NeverDestroyed<ASCIILiteral> lowerClosedUpperOpenKey("SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
-    static NeverDestroyed<ASCIILiteral> lowerClosedUpperClosedKey("SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
-    static NeverDestroyed<ASCIILiteral> lowerOpenUpperOpenValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
-    static NeverDestroyed<ASCIILiteral> lowerOpenUpperClosedValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
-    static NeverDestroyed<ASCIILiteral> lowerClosedUpperOpenValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
-    static NeverDestroyed<ASCIILiteral> lowerClosedUpperClosedValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
+    static const char* const lowerOpenUpperOpenKey ="SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
+    static const char* const lowerOpenUpperClosedKey = "SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
+    static const char* const lowerClosedUpperOpenKey = "SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
+    static const char* const lowerClosedUpperClosedKey = "SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
+    static const char* const lowerOpenUpperOpenValue = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
+    static const char* const lowerOpenUpperClosedValue = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
+    static const char* const lowerClosedUpperOpenValue = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;";
+    static const char* const lowerClosedUpperClosedValue = "SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;";
 
     if (getAllRecordsData.getAllType == IndexedDB::GetAllType::Keys) {
         if (getAllRecordsData.keyRangeData.lowerOpen) {
             if (getAllRecordsData.keyRangeData.upperOpen)
-                return cachedStatement(SQL::GetAllKeyRecordsLowerOpenUpperOpen, lowerOpenUpperOpenKey.get());
-            return cachedStatement(SQL::GetAllKeyRecordsLowerOpenUpperClosed, lowerOpenUpperClosedKey.get());
+                return cachedStatement(SQL::GetAllKeyRecordsLowerOpenUpperOpen, lowerOpenUpperOpenKey);
+            return cachedStatement(SQL::GetAllKeyRecordsLowerOpenUpperClosed, lowerOpenUpperClosedKey);
         }
 
         if (getAllRecordsData.keyRangeData.upperOpen)
-            return cachedStatement(SQL::GetAllKeyRecordsLowerClosedUpperOpen, lowerClosedUpperOpenKey.get());
-        return cachedStatement(SQL::GetAllKeyRecordsLowerClosedUpperClosed, lowerClosedUpperClosedKey.get());
+            return cachedStatement(SQL::GetAllKeyRecordsLowerClosedUpperOpen, lowerClosedUpperOpenKey);
+        return cachedStatement(SQL::GetAllKeyRecordsLowerClosedUpperClosed, lowerClosedUpperClosedKey);
     }
 
     if (getAllRecordsData.keyRangeData.lowerOpen) {
         if (getAllRecordsData.keyRangeData.upperOpen)
-            return cachedStatement(SQL::GetValueRecordsLowerOpenUpperOpen, lowerOpenUpperOpenValue.get());
-        return cachedStatement(SQL::GetValueRecordsLowerOpenUpperClosed, lowerOpenUpperClosedValue.get());
+            return cachedStatement(SQL::GetValueRecordsLowerOpenUpperOpen, lowerOpenUpperOpenValue);
+        return cachedStatement(SQL::GetValueRecordsLowerOpenUpperClosed, lowerOpenUpperClosedValue);
     }
 
     if (getAllRecordsData.keyRangeData.upperOpen)
-        return cachedStatement(SQL::GetValueRecordsLowerClosedUpperOpen, lowerClosedUpperOpenValue.get());
-    return cachedStatement(SQL::GetValueRecordsLowerClosedUpperClosed, lowerClosedUpperClosedValue.get());
+        return cachedStatement(SQL::GetValueRecordsLowerClosedUpperOpen, lowerClosedUpperOpenValue);
+    return cachedStatement(SQL::GetValueRecordsLowerClosedUpperClosed, lowerClosedUpperClosedValue);
 }
 
 IDBError SQLiteIDBBackingStore::getAllObjectStoreRecords(const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData& getAllRecordsData, IDBGetAllResult& result)
index dfff8cf..24ce373 100644 (file)
@@ -43,7 +43,7 @@ namespace WebCore {
 #define STRING_FUNCTION(name) \
     static const String& name##String() \
     { \
-        static NeverDestroyed<const String> name { ASCIILiteral(#name) }; \
+        static NeverDestroyed<const String> name(MAKE_STATIC_STRING_IMPL(#name)); \
         return name; \
     }
 
index 9029afc..848c3df 100644 (file)
@@ -41,7 +41,7 @@ namespace WebCore {
 #define STRING_FUNCTION(name) \
     static const String& name##String() \
     { \
-        static NeverDestroyed<const String> name { ASCIILiteral(#name) }; \
+        static NeverDestroyed<const String> name(MAKE_STATIC_STRING_IMPL(#name)); \
         return name; \
     }
 
index ac64dc2..53cf7ed 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2015, 2016 Ericsson AB. All rights reserved.
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -51,7 +51,7 @@ namespace WebCore {
 #define STRING_FUNCTION(name) \
     static const String& name##String() \
     { \
-        static NeverDestroyed<const String> name { ASCIILiteral(#name) }; \
+        static NeverDestroyed<const String> name(MAKE_STATIC_STRING_IMPL(#name)); \
         return name; \
     }
 
index 010efb7..1dd0ef4 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2011, Google Inc. All rights reserved.
  * Copyright (C) 2012, Samsung Electronics. All rights reserved.
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -117,9 +118,9 @@ ExceptionOr<void> NavigatorContentUtils::registerProtocolHandler(Navigator& navi
 
 static String customHandlersStateString(const NavigatorContentUtilsClient::CustomHandlersState state)
 {
-    static NeverDestroyed<String> newHandler(ASCIILiteral("new"));
-    static NeverDestroyed<String> registeredHandler(ASCIILiteral("registered"));
-    static NeverDestroyed<String> declinedHandler(ASCIILiteral("declined"));
+    static NeverDestroyed<String> newHandler(MAKE_STATIC_STRING_IMPL("new"));
+    static NeverDestroyed<String> registeredHandler(MAKE_STATIC_STRING_IMPL("registered"));
+    static NeverDestroyed<String> declinedHandler(MAKE_STATIC_STRING_IMPL("declined"));
 
     switch (state) {
     case NavigatorContentUtilsClient::CustomHandlersNew:
@@ -136,7 +137,7 @@ static String customHandlersStateString(const NavigatorContentUtilsClient::Custo
 
 ExceptionOr<String> NavigatorContentUtils::isProtocolHandlerRegistered(Navigator& navigator, const String& scheme, const String& url)
 {
-    static NeverDestroyed<String> declined(ASCIILiteral("declined"));
+    static NeverDestroyed<String> declined(MAKE_STATIC_STRING_IMPL("declined"));
 
     if (!navigator.frame())
         return String { declined };
index 9b632b2..69e48c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -188,8 +188,8 @@ void SpeechSynthesis::handleSpeakingCompleted(SpeechSynthesisUtterance& utteranc
 
 void SpeechSynthesis::boundaryEventOccurred(PlatformSpeechSynthesisUtterance& utterance, SpeechBoundary boundary, unsigned charIndex)
 {
-    static NeverDestroyed<const String> wordBoundaryString(ASCIILiteral("word"));
-    static NeverDestroyed<const String> sentenceBoundaryString(ASCIILiteral("sentence"));
+    static NeverDestroyed<const String> wordBoundaryString(MAKE_STATIC_STRING_IMPL("word"));
+    static NeverDestroyed<const String> sentenceBoundaryString(MAKE_STATIC_STRING_IMPL("sentence"));
 
     ASSERT(utterance.client());
 
index a59d168..f1d50fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009-2011 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -83,21 +83,21 @@ MediaControlElementType AccessibilityMediaControl::controlType() const
 
 const String& AccessibilityMediaControl::controlTypeName() const
 {
-    static NeverDestroyed<const String> mediaEnterFullscreenButtonName(ASCIILiteral("EnterFullscreenButton"));
-    static NeverDestroyed<const String> mediaExitFullscreenButtonName(ASCIILiteral("ExitFullscreenButton"));
-    static NeverDestroyed<const String> mediaMuteButtonName(ASCIILiteral("MuteButton"));
-    static NeverDestroyed<const String> mediaPlayButtonName(ASCIILiteral("PlayButton"));
-    static NeverDestroyed<const String> mediaSeekBackButtonName(ASCIILiteral("SeekBackButton"));
-    static NeverDestroyed<const String> mediaSeekForwardButtonName(ASCIILiteral("SeekForwardButton"));
-    static NeverDestroyed<const String> mediaRewindButtonName(ASCIILiteral("RewindButton"));
-    static NeverDestroyed<const String> mediaReturnToRealtimeButtonName(ASCIILiteral("ReturnToRealtimeButton"));
-    static NeverDestroyed<const String> mediaUnMuteButtonName(ASCIILiteral("UnMuteButton"));
-    static NeverDestroyed<const String> mediaPauseButtonName(ASCIILiteral("PauseButton"));
-    static NeverDestroyed<const String> mediaStatusDisplayName(ASCIILiteral("StatusDisplay"));
-    static NeverDestroyed<const String> mediaCurrentTimeDisplay(ASCIILiteral("CurrentTimeDisplay"));
-    static NeverDestroyed<const String> mediaTimeRemainingDisplay(ASCIILiteral("TimeRemainingDisplay"));
-    static NeverDestroyed<const String> mediaShowClosedCaptionsButtonName(ASCIILiteral("ShowClosedCaptionsButton"));
-    static NeverDestroyed<const String> mediaHideClosedCaptionsButtonName(ASCIILiteral("HideClosedCaptionsButton"));
+    static NeverDestroyed<const String> mediaEnterFullscreenButtonName(MAKE_STATIC_STRING_IMPL("EnterFullscreenButton"));
+    static NeverDestroyed<const String> mediaExitFullscreenButtonName(MAKE_STATIC_STRING_IMPL("ExitFullscreenButton"));
+    static NeverDestroyed<const String> mediaMuteButtonName(MAKE_STATIC_STRING_IMPL("MuteButton"));
+    static NeverDestroyed<const String> mediaPlayButtonName(MAKE_STATIC_STRING_IMPL("PlayButton"));
+    static NeverDestroyed<const String> mediaSeekBackButtonName(MAKE_STATIC_STRING_IMPL("SeekBackButton"));
+    static NeverDestroyed<const String> mediaSeekForwardButtonName(MAKE_STATIC_STRING_IMPL("SeekForwardButton"));
+    static NeverDestroyed<const String> mediaRewindButtonName(MAKE_STATIC_STRING_IMPL("RewindButton"));
+    static NeverDestroyed<const String> mediaReturnToRealtimeButtonName(MAKE_STATIC_STRING_IMPL("ReturnToRealtimeButton"));
+    static NeverDestroyed<const String> mediaUnMuteButtonName(MAKE_STATIC_STRING_IMPL("UnMuteButton"));
+    static NeverDestroyed<const String> mediaPauseButtonName(MAKE_STATIC_STRING_IMPL("PauseButton"));
+    static NeverDestroyed<const String> mediaStatusDisplayName(MAKE_STATIC_STRING_IMPL("StatusDisplay"));
+    static NeverDestroyed<const String> mediaCurrentTimeDisplay(MAKE_STATIC_STRING_IMPL("CurrentTimeDisplay"));
+    static NeverDestroyed<const String> mediaTimeRemainingDisplay(MAKE_STATIC_STRING_IMPL("TimeRemainingDisplay"));
+    static NeverDestroyed<const String> mediaShowClosedCaptionsButtonName(MAKE_STATIC_STRING_IMPL("ShowClosedCaptionsButton"));
+    static NeverDestroyed<const String> mediaHideClosedCaptionsButtonName(MAKE_STATIC_STRING_IMPL("HideClosedCaptionsButton"));
 
     switch (controlType()) {
     case MediaEnterFullscreenButton:
@@ -156,7 +156,7 @@ void AccessibilityMediaControl::accessibilityText(Vector<AccessibilityText>& tex
 
 String AccessibilityMediaControl::title() const
 {
-    static NeverDestroyed<const String> controlsPanel(ASCIILiteral("ControlsPanel"));
+    static NeverDestroyed<const String> controlsPanel(MAKE_STATIC_STRING_IMPL("ControlsPanel"));
 
     if (controlType() == MediaControlsPanel)
         return localizedMediaControlElementString(controlsPanel);
@@ -245,8 +245,8 @@ bool AccessibilityMediaControlsContainer::controllingVideoElement() const
 
 const String& AccessibilityMediaControlsContainer::elementTypeName() const
 {
-    static NeverDestroyed<const String> videoElement(ASCIILiteral("VideoElement"));
-    static NeverDestroyed<const String> audioElement(ASCIILiteral("AudioElement"));
+    static NeverDestroyed<const String> videoElement(MAKE_STATIC_STRING_IMPL("VideoElement"));
+    static NeverDestroyed<const String> audioElement(MAKE_STATIC_STRING_IMPL("AudioElement"));
 
     if (controllingVideoElement())
         return videoElement;
@@ -283,7 +283,7 @@ String AccessibilityMediaTimeline::valueDescription() const
 
 String AccessibilityMediaTimeline::helpText() const
 {
-    static NeverDestroyed<const String> slider(ASCIILiteral("Slider"));
+    static NeverDestroyed<const String> slider(MAKE_STATIC_STRING_IMPL("Slider"));
     return localizedMediaControlElementHelpText(slider);
 }
 
@@ -314,8 +314,8 @@ bool AccessibilityMediaTimeDisplay::computeAccessibilityIsIgnored() const
 
 String AccessibilityMediaTimeDisplay::accessibilityDescription() const
 {
-    static NeverDestroyed<const String> currentTimeDisplay(ASCIILiteral("CurrentTimeDisplay"));
-    static NeverDestroyed<const String> timeRemainingDisplay(ASCIILiteral("TimeRemainingDisplay"));
+    static NeverDestroyed<const String> currentTimeDisplay(MAKE_STATIC_STRING_IMPL("CurrentTimeDisplay"));
+    static NeverDestroyed<const String> timeRemainingDisplay(MAKE_STATIC_STRING_IMPL("TimeRemainingDisplay"));
 
     if (controlType() == MediaCurrentTimeDisplay)
         return localizedMediaControlElementString(currentTimeDisplay);
index d270b26..9e051a9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003-2016 Apple Inc. All Rights Reserved.
+ *  Copyright (C) 2003-2017 Apple Inc. All Rights Reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -139,8 +139,8 @@ JSObject* JSLazyEventListener::initializeJSFunction(ScriptExecutionContext* exec
 
 static const String& eventParameterName(bool isSVGEvent)
 {
-    static NeverDestroyed<const String> eventString(ASCIILiteral("event"));
-    static NeverDestroyed<const String> evtString(ASCIILiteral("evt"));
+    static NeverDestroyed<const String> eventString(MAKE_STATIC_STRING_IMPL("event"));
+    static NeverDestroyed<const String> evtString(MAKE_STATIC_STRING_IMPL("evt"));
     return isSVGEvent ? evtString : eventString;
 }
 
index 52d4253..a32665c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -221,7 +221,7 @@ BlockedStatus ContentExtensionsBackend::processContentExtensionRulesForLoad(cons
 
 const String& ContentExtensionsBackend::displayNoneCSSRule()
 {
-    static NeverDestroyed<const String> rule(ASCIILiteral("display:none !important;"));
+    static NeverDestroyed<const String> rule(MAKE_STATIC_STRING_IMPL("display:none !important;"));
     return rule;
 }
 
index b9b40dd..cb6ad28 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
- * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2005-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
  * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
@@ -84,13 +84,13 @@ static inline bool elementCanUseSimpleDefaultStyle(const Element& element)
 
 static const MediaQueryEvaluator& screenEval()
 {
-    static NeverDestroyed<const MediaQueryEvaluator> staticScreenEval(String(ASCIILiteral("screen")));
+    static NeverDestroyed<const MediaQueryEvaluator> staticScreenEval(String(MAKE_STATIC_STRING_IMPL("screen")));
     return staticScreenEval;
 }
 
 static const MediaQueryEvaluator& printEval()
 {
-    static NeverDestroyed<const MediaQueryEvaluator> staticPrintEval(String(ASCIILiteral("print")));
+    static NeverDestroyed<const MediaQueryEvaluator> staticPrintEval(String(MAKE_STATIC_STRING_IMPL("print")));
     return staticPrintEval;
 }
 
index e73a47e..a78ffeb 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2004, 2006, 2010, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -239,11 +239,11 @@ void MediaList::reattach(MediaQuerySet* mediaQueries)
 
 static void addResolutionWarningMessageToConsole(Document& document, const String& serializedExpression, const CSSPrimitiveValue& value)
 {
-    static NeverDestroyed<String> mediaQueryMessage(ASCIILiteral("Consider using 'dppx' units instead of '%replacementUnits%', as in CSS '%replacementUnits%' means dots-per-CSS-%lengthUnit%, not dots-per-physical-%lengthUnit%, so does not correspond to the actual '%replacementUnits%' of a screen. In media query expression: "));
-    static NeverDestroyed<String> mediaValueDPI(ASCIILiteral("dpi"));
-    static NeverDestroyed<String> mediaValueDPCM(ASCIILiteral("dpcm"));
-    static NeverDestroyed<String> lengthUnitInch(ASCIILiteral("inch"));
-    static NeverDestroyed<String> lengthUnitCentimeter(ASCIILiteral("centimeter"));
+    static NeverDestroyed<String> mediaQueryMessage(MAKE_STATIC_STRING_IMPL("Consider using 'dppx' units instead of '%replacementUnits%', as in CSS '%replacementUnits%' means dots-per-CSS-%lengthUnit%, not dots-per-physical-%lengthUnit%, so does not correspond to the actual '%replacementUnits%' of a screen. In media query expression: "));
+    static NeverDestroyed<String> mediaValueDPI(MAKE_STATIC_STRING_IMPL("dpi"));
+    static NeverDestroyed<String> mediaValueDPCM(MAKE_STATIC_STRING_IMPL("dpcm"));
+    static NeverDestroyed<String> lengthUnitInch(MAKE_STATIC_STRING_IMPL("inch"));
+    static NeverDestroyed<String> lengthUnitCentimeter(MAKE_STATIC_STRING_IMPL("centimeter"));
 
     String message;
     if (value.isDotsPerInch())
index 3e49d23..b06f1d6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2004, 2006, 2007, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -338,7 +338,7 @@ void StyleSheetContents::parseAuthorStyleSheet(const CachedCSSStyleSheet* cached
 
     if (m_parserContext.needsSiteSpecificQuirks && isStrictParserMode(m_parserContext.mode)) {
         // Work around <https://bugs.webkit.org/show_bug.cgi?id=28350>.
-        static NeverDestroyed<const String> mediaWikiKHTMLFixesStyleSheet(ASCIILiteral("/* KHTML fix stylesheet */\n/* work around the horizontal scrollbars */\n#column-content { margin-left: 0; }\n\n"));
+        static NeverDestroyed<const String> mediaWikiKHTMLFixesStyleSheet(MAKE_STATIC_STRING_IMPL("/* KHTML fix stylesheet */\n/* work around the horizontal scrollbars */\n#column-content { margin-left: 0; }\n\n"));
         // There are two variants of KHTMLFixes.css. One is equal to mediaWikiKHTMLFixesStyleSheet,
         // while the other lacks the second trailing newline.
         if (baseURL().string().endsWith("/KHTMLFixes.css") && !sheetText.isNull() && mediaWikiKHTMLFixesStyleSheet.get().startsWith(sheetText)
index d9ce033..855801f 100644 (file)
@@ -1137,9 +1137,9 @@ ExceptionOr<Ref<Element>> Document::createElementNS(const AtomicString& namespac
 
 String Document::readyState() const
 {
-    static NeverDestroyed<const String> loading(ASCIILiteral("loading"));
-    static NeverDestroyed<const String> interactive(ASCIILiteral("interactive"));
-    static NeverDestroyed<const String> complete(ASCIILiteral("complete"));
+    static NeverDestroyed<const String> loading(MAKE_STATIC_STRING_IMPL("loading"));
+    static NeverDestroyed<const String> interactive(MAKE_STATIC_STRING_IMPL("interactive"));
+    static NeverDestroyed<const String> complete(MAKE_STATIC_STRING_IMPL("complete"));
 
     switch (m_readyState) {
     case Loading:
index a7f4451..fdcd223 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Apple, Inc. All Rights Reserved.
+ * Copyright (C) 2016-2017 Apple, Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -72,7 +72,7 @@ void LoadableClassicScript::notifyFinished(CachedResource& resource)
 {
     ASSERT(m_cachedScript);
     if (resource.resourceError().isAccessControl()) {
-        static NeverDestroyed<String> consoleMessage(ASCIILiteral("Cross-origin script load denied by Cross-Origin Resource Sharing policy."));
+        static NeverDestroyed<String> consoleMessage(MAKE_STATIC_STRING_IMPL("Cross-origin script load denied by Cross-Origin Resource Sharing policy."));
         m_error = Error {
             ErrorType::CrossOriginLoad,
             ConsoleMessage {
index 4dadfba..b86addf 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2012 Google Inc. All rights reserved.
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -44,8 +45,8 @@ const QualifiedName& pseudoElementTagName()
 
 String PseudoElement::pseudoElementNameForEvents(PseudoId pseudoId)
 {
-    static NeverDestroyed<const String> after(ASCIILiteral("::after"));
-    static NeverDestroyed<const String> before(ASCIILiteral("::before"));
+    static NeverDestroyed<const String> after(MAKE_STATIC_STRING_IMPL("::after"));
+    static NeverDestroyed<const String> before(MAKE_STATIC_STRING_IMPL("::before"));
     switch (pseudoId) {
     case AFTER:
         return after;
index d3bb0af..ae16aae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2009, 2010 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -257,7 +257,7 @@ bool MarkupAccumulator::shouldAddNamespaceElement(const Element& element)
     if (prefix.isEmpty())
         return !element.hasAttribute(xmlnsAtom);
 
-    static NeverDestroyed<String> xmlnsWithColon(ASCIILiteral("xmlns:"));
+    static NeverDestroyed<String> xmlnsWithColon(MAKE_STATIC_STRING_IMPL("xmlns:"));
     return !element.hasAttribute(xmlnsWithColon.get() + prefix);
 }
 
index 6fdce48..ac61f76 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple, Inc.  All rights reserved.
+ * Copyright (C) 2014-2017 Apple, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -662,7 +662,7 @@ NSArray *DataDetection::detectContentInRange(RefPtr<Range>&, DataDetectorTypes,
 
 const String& DataDetection::dataDetectorURLProtocol()
 {
-    static NeverDestroyed<String> protocol(ASCIILiteral("x-apple-data-detectors"));
+    static NeverDestroyed<String> protocol(MAKE_STATIC_STRING_IMPL("x-apple-data-detectors"));
     return protocol;
 }
 
index 8d61e57..a4f8513 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved.
  * Copyright (C) 2011 Igalia S.L.
  * Copyright (C) 2011 Motorola Mobility. All rights reserved.
@@ -213,8 +213,8 @@ void StyledMarkupAccumulator::appendStyleNodeOpenTag(StringBuilder& out, StylePr
 
 const String& StyledMarkupAccumulator::styleNodeCloseTag(bool isBlock)
 {
-    static NeverDestroyed<const String> divClose(ASCIILiteral("</div>"));
-    static NeverDestroyed<const String> styleSpanClose(ASCIILiteral("</span>"));
+    static NeverDestroyed<const String> divClose(MAKE_STATIC_STRING_IMPL("</div>"));
+    static NeverDestroyed<const String> styleSpanClose(MAKE_STATIC_STRING_IMPL("</span>"));
     return isBlock ? divClose : styleSpanClose;
 }
 
@@ -576,7 +576,7 @@ static Node* highestAncestorToWrapMarkup(const Range* range, EAnnotateForInterch
 static String createMarkupInternal(Document& document, const Range& range, Vector<Node*>* nodes,
     EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsoluteURLs shouldResolveURLs)
 {
-    static NeverDestroyed<const String> interchangeNewlineString(ASCIILiteral("<br class=\"" AppleInterchangeNewline "\">"));
+    static NeverDestroyed<const String> interchangeNewlineString(MAKE_STATIC_STRING_IMPL("<br class=\"" AppleInterchangeNewline "\">"));
 
     bool collapsed = range.collapsed();
     if (collapsed)
index cb824e4..f9fe4b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2010, 2011, 2012 Google Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
@@ -387,7 +387,7 @@ static String formStateSignature()
     // In the legacy version of serialized state, the first item was a name
     // attribute value of a form control. The following string literal should
     // contain some characters which are rarely used for name attribute values.
-    static NeverDestroyed<String> signature(ASCIILiteral("\n\r?% WebKit serialized form state version 8 \n\r=&"));
+    static NeverDestroyed<String> signature(MAKE_STATIC_STRING_IMPL("\n\r?% WebKit serialized form state version 8 \n\r=&"));
     return signature;
 }
 
index 99ca100..b211be9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2010 Google Inc. All rights reserved.
  * Copyright (C) 2012 Samsung Electronics. All rights reserved.
  *
@@ -65,8 +65,8 @@ bool ImageInputType::appendFormData(FormDataList& encoding, bool) const
         return true;
     }
 
-    static NeverDestroyed<String> dotXString(ASCIILiteral(".x"));
-    static NeverDestroyed<String> dotYString(ASCIILiteral(".y"));
+    static NeverDestroyed<String> dotXString(MAKE_STATIC_STRING_IMPL(".x"));
+    static NeverDestroyed<String> dotYString(MAKE_STATIC_STRING_IMPL(".y"));
     encoding.appendData(name + dotXString.get(), m_clickLocation.x());
     encoding.appendData(name + dotYString.get(), m_clickLocation.y());
 
index f7c712c..1314e48 100644 (file)
@@ -352,7 +352,7 @@ void CanvasRenderingContext2D::realizeSaves()
         realizeSavesLoop();
 
     if (m_unrealizedSaveCount) {
-        static NeverDestroyed<String> consoleMessage(ASCIILiteral("CanvasRenderingContext2D.save() has been called without a matching restore() too many times. Ignoring save()."));
+        static NeverDestroyed<String> consoleMessage(MAKE_STATIC_STRING_IMPL("CanvasRenderingContext2D.save() has been called without a matching restore() too many times. Ignoring save()."));
         canvas().document().addConsoleMessage(MessageSource::Rendering, MessageLevel::Error, consoleMessage);
     }
 }
@@ -1981,7 +1981,7 @@ ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::webkitGetImageDataHD(fl
 ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::getImageData(ImageBuffer::CoordinateSystem coordinateSystem, float sx, float sy, float sw, float sh) const
 {
     if (!canvas().originClean()) {
-        static NeverDestroyed<String> consoleMessage(ASCIILiteral("Unable to get image data from canvas because the canvas has been tainted by cross-origin data."));
+        static NeverDestroyed<String> consoleMessage(MAKE_STATIC_STRING_IMPL("Unable to get image data from canvas because the canvas has been tainted by cross-origin data."));
         canvas().document().addConsoleMessage(MessageSource::Security, MessageLevel::Error, consoleMessage);
         return Exception { SECURITY_ERR };
     }
index 8e1bcc8..8b6dfea 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2011 Adam Barth. All Rights Reserved.
  * Copyright (C) 2011 Daniel Bates (dbates@intudata.com).
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -316,7 +317,7 @@ void XSSAuditor::init(Document* document, XSSAuditorDelegate* auditorDelegate)
 
     String httpBodyAsString;
     if (DocumentLoader* documentLoader = document->frame()->loader().documentLoader()) {
-        static NeverDestroyed<String> XSSProtectionHeader(ASCIILiteral("X-XSS-Protection"));
+        static NeverDestroyed<String> XSSProtectionHeader(MAKE_STATIC_STRING_IMPL("X-XSS-Protection"));
         String headerValue = documentLoader->response().httpHeaderField(XSSProtectionHeader);
         String errorDetails;
         unsigned errorPosition = 0;
@@ -563,7 +564,7 @@ bool XSSAuditor::filterButtonToken(const FilterTokenRequest& request)
 
 bool XSSAuditor::eraseDangerousAttributesIfInjected(const FilterTokenRequest& request)
 {
-    static NeverDestroyed<String> safeJavaScriptURL(ASCIILiteral("javascript:void(0)"));
+    static NeverDestroyed<String> safeJavaScriptURL(MAKE_STATIC_STRING_IMPL("javascript:void(0)"));
 
     bool didBlockScript = false;
     for (size_t i = 0; i < request.token.attributes().size(); ++i) {
index f52d0ec..8a38ce0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011, 2013 Google Inc.  All rights reserved.
- * Copyright (C) 2011-2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -74,31 +74,31 @@ COMPILE_ASSERT(WTF_ARRAY_LENGTH(displayAlignmentMap) == VTTCue::NumberOfAlignmen
 
 static const String& startKeyword()
 {
-    static NeverDestroyed<const String> start(ASCIILiteral("start"));
+    static NeverDestroyed<const String> start(MAKE_STATIC_STRING_IMPL("start"));
     return start;
 }
 
 static const String& middleKeyword()
 {
-    static NeverDestroyed<const String> middle(ASCIILiteral("middle"));
+    static NeverDestroyed<const String> middle(MAKE_STATIC_STRING_IMPL("middle"));
     return middle;
 }
 
 static const String& endKeyword()
 {
-    static NeverDestroyed<const String> end(ASCIILiteral("end"));
+    static NeverDestroyed<const String> end(MAKE_STATIC_STRING_IMPL("end"));
     return end;
 }
 
 static const String& leftKeyword()
 {
-    static NeverDestroyed<const String> left("left");
+    static NeverDestroyed<const String> left(MAKE_STATIC_STRING_IMPL("left"));
     return left;
 }
 
 static const String& rightKeyword()
 {
-    static NeverDestroyed<const String> right("right");
+    static NeverDestroyed<const String> right(MAKE_STATIC_STRING_IMPL("right"));
     return right;
 }
 
@@ -109,13 +109,13 @@ static const String& horizontalKeyword()
 
 static const String& verticalGrowingLeftKeyword()
 {
-    static NeverDestroyed<const String> verticalrl(ASCIILiteral("rl"));
+    static NeverDestroyed<const String> verticalrl(MAKE_STATIC_STRING_IMPL("rl"));
     return verticalrl;
 }
 
 static const String& verticalGrowingRightKeyword()
 {
-    static NeverDestroyed<const String> verticallr(ASCIILiteral("lr"));
+    static NeverDestroyed<const String> verticallr(MAKE_STATIC_STRING_IMPL("lr"));
     return verticallr;
 }
 
@@ -609,7 +609,7 @@ static bool isCueParagraphSeparator(UChar character)
 
 void VTTCue::determineTextDirection()
 {
-    static NeverDestroyed<const String> rtTag(ASCIILiteral("rt"));
+    static NeverDestroyed<const String> rtTag(MAKE_STATIC_STRING_IMPL("rt"));
     createWebVTTNodeTree();
     if (!m_webVTTNodeTree)
         return;
@@ -753,7 +753,7 @@ void VTTCue::calculateDisplayParameters()
     
 void VTTCue::markFutureAndPastNodes(ContainerNode* root, const MediaTime& previousTimestamp, const MediaTime& movieTime)
 {
-    static NeverDestroyed<const String> timestampTag(ASCIILiteral("timestamp"));
+    static NeverDestroyed<const String> timestampTag(MAKE_STATIC_STRING_IMPL("timestamp"));
     
     bool isPastNode = true;
     MediaTime currentTimestamp = previousTimestamp;
index a7fed42..7c1992f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 Google Inc. All rights reserved.
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -77,10 +77,10 @@ enum ForcePseudoClassFlags {
 
 static unsigned computePseudoClassMask(const InspectorArray& pseudoClassArray)
 {
-    static NeverDestroyed<String> active(ASCIILiteral("active"));
-    static NeverDestroyed<String> hover(ASCIILiteral("hover"));
-    static NeverDestroyed<String> focus(ASCIILiteral("focus"));
-    static NeverDestroyed<String> visited(ASCIILiteral("visited"));
+    static NeverDestroyed<String> active(MAKE_STATIC_STRING_IMPL("active"));
+    static NeverDestroyed<String> hover(MAKE_STATIC_STRING_IMPL("hover"));
+    static NeverDestroyed<String> focus(MAKE_STATIC_STRING_IMPL("focus"));
+    static NeverDestroyed<String> visited(MAKE_STATIC_STRING_IMPL("visited"));
     if (!pseudoClassArray.length())
         return PseudoClassNone;
 
index ef3d268..c94f37a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2012 Google Inc. All rights reserved.
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -274,10 +274,10 @@ static RefPtr<IDBKey> idbKeyFromInspectorObject(InspectorObject* key)
     if (!key->getString("type", type))
         return nullptr;
 
-    static NeverDestroyed<const String> numberType(ASCIILiteral("number"));
-    static NeverDestroyed<const String> stringType(ASCIILiteral("string"));
-    static NeverDestroyed<const String> dateType(ASCIILiteral("date"));
-    static NeverDestroyed<const String> arrayType(ASCIILiteral("array"));
+    static NeverDestroyed<const String> numberType(MAKE_STATIC_STRING_IMPL("number"));
+    static NeverDestroyed<const String> stringType(MAKE_STATIC_STRING_IMPL("string"));
+    static NeverDestroyed<const String> dateType(MAKE_STATIC_STRING_IMPL("date"));
+    static NeverDestroyed<const String> arrayType(MAKE_STATIC_STRING_IMPL("array"));
 
     RefPtr<IDBKey> idbKey;
     if (type == numberType) {
index 12c8928..c434931 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011 Google Inc. All rights reserved.
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -205,8 +205,8 @@ void InspectorPageAgent::resourceContent(ErrorString& errorString, Frame* frame,
 //static
 String InspectorPageAgent::sourceMapURLForResource(CachedResource* cachedResource)
 {
-    static NeverDestroyed<String> sourceMapHTTPHeader(ASCIILiteral("SourceMap"));
-    static NeverDestroyed<String> sourceMapHTTPHeaderDeprecated(ASCIILiteral("X-SourceMap"));
+    static NeverDestroyed<String> sourceMapHTTPHeader(MAKE_STATIC_STRING_IMPL("SourceMap"));
+    static NeverDestroyed<String> sourceMapHTTPHeaderDeprecated(MAKE_STATIC_STRING_IMPL("X-SourceMap"));
 
     if (!cachedResource)
         return String();
index a86ed13..d713736 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011 Google Inc. All rights reserved.
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -73,8 +73,8 @@ void PageDebuggerAgent::disable(bool isBeingDestroyed)
 
 String PageDebuggerAgent::sourceMapURLForScript(const Script& script)
 {
-    static NeverDestroyed<String> sourceMapHTTPHeader(ASCIILiteral("SourceMap"));
-    static NeverDestroyed<String> sourceMapHTTPHeaderDeprecated(ASCIILiteral("X-SourceMap"));
+    static NeverDestroyed<String> sourceMapHTTPHeader(MAKE_STATIC_STRING_IMPL("SourceMap"));
+    static NeverDestroyed<String> sourceMapHTTPHeaderDeprecated(MAKE_STATIC_STRING_IMPL("X-SourceMap"));
 
     if (!script.url.isEmpty()) {
         CachedResource* resource = m_pageAgent->cachedResource(&m_page.mainFrame(), URL(ParsedURLString, script.url));
index c286682..015c0e4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -287,7 +287,7 @@ void ImageLoader::notifyFinished(CachedResource& resource)
         m_hasPendingErrorEvent = true;
         errorEventSender().dispatchEventSoon(*this);
 
-        static NeverDestroyed<String> consoleMessage(ASCIILiteral("Cross-origin image load denied by Cross-Origin Resource Sharing policy."));
+        static NeverDestroyed<String> consoleMessage(MAKE_STATIC_STRING_IMPL("Cross-origin image load denied by Cross-Origin Resource Sharing policy."));
         element().document().addConsoleMessage(MessageSource::Security, MessageLevel::Error, consoleMessage);
 
         ASSERT(!m_hasPendingLoadEvent);
index 22157e9..742c3a1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011 Google Inc.  All rights reserved.
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -117,7 +117,7 @@ void TextTrackLoader::deprecatedDidReceiveCachedResource(CachedResource& resourc
 
 void TextTrackLoader::corsPolicyPreventedLoad()
 {
-    static NeverDestroyed<String> consoleMessage(ASCIILiteral("Cross-origin text track load denied by Cross-Origin Resource Sharing policy."));
+    static NeverDestroyed<String> consoleMessage(MAKE_STATIC_STRING_IMPL("Cross-origin text track load denied by Cross-Origin Resource Sharing policy."));
     Document* document = downcast<Document>(m_scriptExecutionContext);
     document->addConsoleMessage(MessageSource::Security, MessageLevel::Error, consoleMessage);
     m_state = Failed;
index 1e35376..48f88c5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
  *
  * Redistribution and use in source and binary forms, with or without
@@ -880,7 +880,7 @@ String IconDatabase::databasePath() const
 
 String IconDatabase::defaultDatabaseFilename()
 {
-    static NeverDestroyed<String> defaultDatabaseFilename(ASCIILiteral("WebpageIcons.db"));
+    static NeverDestroyed<String> defaultDatabaseFilename(MAKE_STATIC_STRING_IMPL("WebpageIcons.db"));
     return defaultDatabaseFilename.get().isolatedCopy();
 }
 
index 704b50e..f4ec007 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -379,9 +379,9 @@ bool CaptionUserPreferencesMediaAF::captionStrokeWidthForFont(float fontSize, co
 
 String CaptionUserPreferencesMediaAF::captionsTextEdgeCSS() const
 {
-    static NeverDestroyed<const String> edgeStyleRaised(ASCIILiteral(" -.1em -.1em .16em "));
-    static NeverDestroyed<const String> edgeStyleDepressed(ASCIILiteral(" .1em .1em .16em "));
-    static NeverDestroyed<const String> edgeStyleDropShadow(ASCIILiteral(" 0 .1em .16em "));
+    static NeverDestroyed<const String> edgeStyleRaised(MAKE_STATIC_STRING_IMPL(" -.1em -.1em .16em "));
+    static NeverDestroyed<const String> edgeStyleDepressed(MAKE_STATIC_STRING_IMPL(" .1em .1em .16em "));
+    static NeverDestroyed<const String> edgeStyleDropShadow(MAKE_STATIC_STRING_IMPL(" 0 .1em .16em "));
 
     MACaptionAppearanceBehavior behavior;
     MACaptionAppearanceTextEdgeStyle textEdgeStyle = MACaptionAppearanceGetTextEdgeStyle(kMACaptionAppearanceDomainUser, &behavior);
index 38fa1e9..a5b5d98 100644 (file)
@@ -535,7 +535,7 @@ bool SecurityOrigin::isSameSchemeHostPort(const SecurityOrigin& other) const
 URL SecurityOrigin::urlWithUniqueSecurityOrigin()
 {
     ASSERT(isMainThread());
-    static NeverDestroyed<URL> uniqueSecurityOriginURL(ParsedURLString, ASCIILiteral("data:,"));
+    static NeverDestroyed<URL> uniqueSecurityOriginURL(ParsedURLString, MAKE_STATIC_STRING_IMPL("data:,"));
     return uniqueSecurityOriginURL;
 }
 
index d431ee7..4dab547 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -63,7 +63,7 @@ bool UserContentURLPattern::matchesPatterns(const URL& url, const Vector<String>
 
 bool UserContentURLPattern::parse(const String& pattern)
 {
-    static NeverDestroyed<const String> schemeSeparator(ASCIILiteral("://"));
+    static NeverDestroyed<const String> schemeSeparator(MAKE_STATIC_STRING_IMPL("://"));
 
     size_t schemeEndPos = pattern.find(schemeSeparator);
     if (schemeEndPos == notFound)
index e5a440d..81be9c5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2016 Apple Inc.  All rights reserved.
+ * Copyright (C) 2006-2017 Apple Inc.  All rights reserved.
  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
  *
  * Redistribution and use in source and binary forms, with or without
@@ -697,7 +697,7 @@ HashSet<String, ASCIICaseInsensitiveHash>& MIMETypeRegistry::getUnsupportedTextM
 
 const String& defaultMIMEType()
 {
-    static NeverDestroyed<const String> defaultMIMEType(ASCIILiteral("application/octet-stream"));
+    static NeverDestroyed<const String> defaultMIMEType(MAKE_STATIC_STRING_IMPL("application/octet-stream"));
     return defaultMIMEType;
 }
 
index 1affdd8..8093b6f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -165,7 +165,7 @@ bool Animation::animationsMatch(const Animation& other, bool matchPlayStates) co
 
 const String& Animation::initialName()
 {
-    static NeverDestroyed<String> initialValue(ASCIILiteral("none"));
+    static NeverDestroyed<String> initialValue(MAKE_STATIC_STRING_IMPL("none"));
     return initialValue;
 }
 
index a3a4512..53c429b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -558,7 +558,7 @@ void MediaPlayerPrivateMediaSourceAVFObjC::prepareForRendering()
 
 String MediaPlayerPrivateMediaSourceAVFObjC::engineDescription() const
 {
-    static NeverDestroyed<String> description(ASCIILiteral("AVFoundation MediaSource Engine"));
+    static NeverDestroyed<String> description(MAKE_STATIC_STRING_IMPL("AVFoundation MediaSource Engine"));
     return description;
 }
 
index f72e365..3599b79 100644 (file)
@@ -1059,7 +1059,7 @@ void MediaPlayerPrivateMediaStreamAVFObjC::acceleratedRenderingStateChanged()
 
 String MediaPlayerPrivateMediaStreamAVFObjC::engineDescription() const
 {
-    static NeverDestroyed<String> description(ASCIILiteral("AVFoundation MediaStream Engine"));
+    static NeverDestroyed<String> description(MAKE_STATIC_STRING_IMPL("AVFoundation MediaStream Engine"));
     return description;
 }
 
index f3c871e..34c1fc6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -671,9 +671,9 @@ RefPtr<Font> FontCache::similarFont(const FontDescription& description, const At
     }
 #endif
 
-    static NeverDestroyed<String> arabic(ASCIILiteral("Arabic"));
-    static NeverDestroyed<String> pashto(ASCIILiteral("Pashto"));
-    static NeverDestroyed<String> urdu(ASCIILiteral("Urdu"));
+    static NeverDestroyed<String> arabic(MAKE_STATIC_STRING_IMPL("Arabic"));
+    static NeverDestroyed<String> pashto(MAKE_STATIC_STRING_IMPL("Pashto"));
+    static NeverDestroyed<String> urdu(MAKE_STATIC_STRING_IMPL("Urdu"));
     static String* matchWords[3] = { &arabic.get(), &pashto.get(), &urdu.get() };
     static NeverDestroyed<AtomicString> geezaPlain("GeezaPro", AtomicString::ConstructFromLiteral);
     static NeverDestroyed<AtomicString> geezaBold("GeezaPro-Bold", AtomicString::ConstructFromLiteral);
index 0025761..8422c64 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2012, 2014, 2016 Igalia S.L.
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -64,7 +65,7 @@ static const String platformVersionForUAString()
     // OS X or anything on ARM triggers mobile versions of some websites.
     //
     // FIXME: The final result should include OS version, e.g. "Intel Mac OS X 10_8_4".
-    static NeverDestroyed<const String> uaOSVersion(ASCIILiteral("Intel Mac OS X"));
+    static NeverDestroyed<const String> uaOSVersion(MAKE_STATIC_STRING_IMPL("Intel Mac OS X"));
     return uaOSVersion;
 #endif
 }
index c8b134e..6f1912d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -80,7 +80,7 @@ MockTrackBox::MockTrackBox(ArrayBuffer* data)
 
 const String& MockTrackBox::type()
 {
-    static NeverDestroyed<String> trak(ASCIILiteral("trak"));
+    static NeverDestroyed<String> trak(MAKE_STATIC_STRING_IMPL("trak"));
     return trak;
 }
 
@@ -109,7 +109,7 @@ MockInitializationBox::MockInitializationBox(ArrayBuffer* data)
 
 const String& MockInitializationBox::type()
 {
-    static NeverDestroyed<String> init(ASCIILiteral("init"));
+    static NeverDestroyed<String> init(MAKE_STATIC_STRING_IMPL("init"));
     return init;
 }
 
@@ -137,7 +137,7 @@ MockSampleBox::MockSampleBox(ArrayBuffer* data)
 
 const String& MockSampleBox::type()
 {
-    static NeverDestroyed<String> smpl(ASCIILiteral("smpl"));
+    static NeverDestroyed<String> smpl(MAKE_STATIC_STRING_IMPL("smpl"));
     return smpl;
 }
 
index 72df220..5595eb3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,25 +34,25 @@ namespace HTTPHeaderValues {
 
 const String& textPlainContentType()
 {
-    static NeverDestroyed<const String> contentType(ASCIILiteral("text/plain;charset=UTF-8"));
+    static NeverDestroyed<const String> contentType(MAKE_STATIC_STRING_IMPL("text/plain;charset=UTF-8"));
     return contentType;
 }
 
 const String& formURLEncodedContentType()
 {
-    static NeverDestroyed<const String> contentType(ASCIILiteral("application/x-www-form-urlencoded;charset=UTF-8"));
+    static NeverDestroyed<const String> contentType(MAKE_STATIC_STRING_IMPL("application/x-www-form-urlencoded;charset=UTF-8"));
     return contentType;
 }
 
 const String& noCache()
 {
-    static NeverDestroyed<const String> value(ASCIILiteral("no-cache"));
+    static NeverDestroyed<const String> value(MAKE_STATIC_STRING_IMPL("no-cache"));
     return value;
 }
 
 const String& maxAge0()
 {
-    static NeverDestroyed<const String> value(ASCIILiteral("max-age=0"));
+    static NeverDestroyed<const String> value(MAKE_STATIC_STRING_IMPL("max-age=0"));
     return value;
 }
 
index 158e2d9..6220a2b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
  * Copyright (C) 2009 Google Inc. All rights reserved.
  * Copyright (C) 2011 Apple Inc. All Rights Reserved.
@@ -384,14 +384,14 @@ void findCharsetInMediaType(const String& mediaType, unsigned int& charsetPos, u
 
 XSSProtectionDisposition parseXSSProtectionHeader(const String& header, String& failureReason, unsigned& failurePosition, String& reportURL)
 {
-    static NeverDestroyed<String> failureReasonInvalidToggle(ASCIILiteral("expected 0 or 1"));
-    static NeverDestroyed<String> failureReasonInvalidSeparator(ASCIILiteral("expected semicolon"));
-    static NeverDestroyed<String> failureReasonInvalidEquals(ASCIILiteral("expected equals sign"));
-    static NeverDestroyed<String> failureReasonInvalidMode(ASCIILiteral("invalid mode directive"));
-    static NeverDestroyed<String> failureReasonInvalidReport(ASCIILiteral("invalid report directive"));
-    static NeverDestroyed<String> failureReasonDuplicateMode(ASCIILiteral("duplicate mode directive"));
-    static NeverDestroyed<String> failureReasonDuplicateReport(ASCIILiteral("duplicate report directive"));
-    static NeverDestroyed<String> failureReasonInvalidDirective(ASCIILiteral("unrecognized directive"));
+    static NeverDestroyed<String> failureReasonInvalidToggle(MAKE_STATIC_STRING_IMPL("expected 0 or 1"));
+    static NeverDestroyed<String> failureReasonInvalidSeparator(MAKE_STATIC_STRING_IMPL("expected semicolon"));
+    static NeverDestroyed<String> failureReasonInvalidEquals(MAKE_STATIC_STRING_IMPL("expected equals sign"));
+    static NeverDestroyed<String> failureReasonInvalidMode(MAKE_STATIC_STRING_IMPL("invalid mode directive"));
+    static NeverDestroyed<String> failureReasonInvalidReport(MAKE_STATIC_STRING_IMPL("invalid report directive"));
+    static NeverDestroyed<String> failureReasonDuplicateMode(MAKE_STATIC_STRING_IMPL("duplicate mode directive"));
+    static NeverDestroyed<String> failureReasonDuplicateReport(MAKE_STATIC_STRING_IMPL("duplicate report directive"));
+    static NeverDestroyed<String> failureReasonInvalidDirective(MAKE_STATIC_STRING_IMPL("unrecognized directive"));
 
     unsigned pos = 0;
 
index fdef95d..51d8378 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -71,7 +71,7 @@ using WebCore::SerializedScriptValue;
 
 const String& InputTraits<MemoizedDOMResultBase>::type()
 {
-    static NeverDestroyed<const String> type(ASCIILiteral("MemoizedDOMResult"));
+    static NeverDestroyed<const String> type(MAKE_STATIC_STRING_IMPL("MemoizedDOMResult"));
     return type;
 }
 
index 4f94fe4..fa0ef14 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org>
  * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -130,27 +131,27 @@ const String& SVGTransformValue::transformTypePrefixForParsing(SVGTransformType
     case SVG_TRANSFORM_UNKNOWN:
         return emptyString();
     case SVG_TRANSFORM_MATRIX: {
-        static NeverDestroyed<String> matrixString(ASCIILiteral("matrix("));
+        static NeverDestroyed<String> matrixString(MAKE_STATIC_STRING_IMPL("matrix("));
         return matrixString;
     }
     case SVG_TRANSFORM_TRANSLATE: {
-        static NeverDestroyed<String> translateString(ASCIILiteral("translate("));
+        static NeverDestroyed<String> translateString(MAKE_STATIC_STRING_IMPL("translate("));
         return translateString;
     }
     case SVG_TRANSFORM_SCALE: {
-        static NeverDestroyed<String> scaleString(ASCIILiteral("scale("));
+        static NeverDestroyed<String> scaleString(MAKE_STATIC_STRING_IMPL("scale("));
         return scaleString;
     }
     case SVG_TRANSFORM_ROTATE: {
-        static NeverDestroyed<String> rotateString(ASCIILiteral("rotate("));
+        static NeverDestroyed<String> rotateString(MAKE_STATIC_STRING_IMPL("rotate("));
         return rotateString;
     }    
     case SVG_TRANSFORM_SKEWX: {
-        static NeverDestroyed<String> skewXString(ASCIILiteral("skewX("));
+        static NeverDestroyed<String> skewXString(MAKE_STATIC_STRING_IMPL("skewX("));
         return skewXString;
     }
     case SVG_TRANSFORM_SKEWY: {
-        static NeverDestroyed<String> skewYString(ASCIILiteral("skewY("));
+        static NeverDestroyed<String> skewYString(MAKE_STATIC_STRING_IMPL("skewY("));
         return skewYString;
     }
     }
index 09b5698..dc7819e 100644 (file)
@@ -1,3 +1,27 @@
+2017-05-04  Mark Lam  <mark.lam@apple.com>
+
+        NeverDestroyed<String>(ASCIILiteral(...)) is not thread safe.
+        https://bugs.webkit.org/show_bug.cgi?id=171586
+        <rdar://problem/31873190>
+
+        Reviewed by Yusuke Suzuki.
+
+        * Shared/API/APIError.cpp:
+        (API::Error::webKitErrorDomain):
+        (API::Error::webKitNetworkErrorDomain):
+        (API::Error::webKitPolicyErrorDomain):
+        (API::Error::webKitPluginErrorDomain):
+        (API::Error::webKitDownloadErrorDomain):
+        (API::Error::webKitPrintErrorDomain):
+        * Shared/WebPreferencesKeys.cpp:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::executeEditCommand):
+        * WebProcess/WebCoreSupport/WebEditorClient.cpp:
+        (WebKit::WebEditorClient::didBeginEditing):
+        (WebKit::WebEditorClient::respondToChangedContents):
+        (WebKit::WebEditorClient::respondToChangedSelection):
+        (WebKit::WebEditorClient::didEndEditing):
+
 2017-05-04  Jeremy Jones  <jeremyj@apple.com>
 
         Add mute to WebPlaybackSessionModel.
index b73c212..3b05b7d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,14 +34,14 @@ namespace API {
 
 const WTF::String& Error::webKitErrorDomain()
 {
-    static NeverDestroyed<WTF::String> webKitErrorDomainString(ASCIILiteral("WebKitErrorDomain"));
+    static NeverDestroyed<WTF::String> webKitErrorDomainString(MAKE_STATIC_STRING_IMPL("WebKitErrorDomain"));
     return webKitErrorDomainString;
 }
 
 const WTF::String& Error::webKitNetworkErrorDomain()
 {
 #if USE(GLIB)
-    static NeverDestroyed<WTF::String> webKitErrorDomainString(ASCIILiteral("WebKitNetworkError"));
+    static NeverDestroyed<WTF::String> webKitErrorDomainString(MAKE_STATIC_STRING_IMPL("WebKitNetworkError"));
     return webKitErrorDomainString;
 #else
     return webKitErrorDomain();
@@ -51,7 +51,7 @@ const WTF::String& Error::webKitNetworkErrorDomain()
 const WTF::String& Error::webKitPolicyErrorDomain()
 {
 #if USE(GLIB)
-    static NeverDestroyed<WTF::String> webKitErrorDomainString(ASCIILiteral("WebKitPolicyError"));
+    static NeverDestroyed<WTF::String> webKitErrorDomainString(MAKE_STATIC_STRING_IMPL("WebKitPolicyError"));
     return webKitErrorDomainString;
 #else
     return webKitErrorDomain();
@@ -61,7 +61,7 @@ const WTF::String& Error::webKitPolicyErrorDomain()
 const WTF::String& Error::webKitPluginErrorDomain()
 {
 #if USE(GLIB)
-    static NeverDestroyed<WTF::String> webKitErrorDomainString(ASCIILiteral("WebKitPluginError"));
+    static NeverDestroyed<WTF::String> webKitErrorDomainString(MAKE_STATIC_STRING_IMPL("WebKitPluginError"));
     return webKitErrorDomainString;
 #else
     return webKitErrorDomain();
@@ -71,7 +71,7 @@ const WTF::String& Error::webKitPluginErrorDomain()
 #if USE(SOUP)
 const WTF::String& Error::webKitDownloadErrorDomain()
 {
-    static NeverDestroyed<WTF::String> webKitErrorDomainString(ASCIILiteral("WebKitDownloadError"));
+    static NeverDestroyed<WTF::String> webKitErrorDomainString(MAKE_STATIC_STRING_IMPL("WebKitDownloadError"));
     return webKitErrorDomainString;
 }
 #endif
@@ -79,7 +79,7 @@ const WTF::String& Error::webKitDownloadErrorDomain()
 #if PLATFORM(GTK)
 const WTF::String& Error::webKitPrintErrorDomain()
 {
-    static NeverDestroyed<WTF::String> webKitErrorDomainString(ASCIILiteral("WebKitPrintError"));
+    static NeverDestroyed<WTF::String> webKitErrorDomainString(MAKE_STATIC_STRING_IMPL("WebKitPrintError"));
     return webKitErrorDomainString;
 }
 #endif
index 8467cd3..b654893 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,7 +34,7 @@ namespace WebPreferencesKey {
 #define DEFINE_KEY_GETTERS(KeyUpper, KeyLower, TypeName, Type, DefaultValue, HumanReadableName, HumanReadableDescription) \
         const String& KeyLower##Key() \
         { \
-            static NeverDestroyed<String> key(ASCIILiteral(#KeyUpper)); \
+            static NeverDestroyed<String> key(MAKE_STATIC_STRING_IMPL(#KeyUpper)); \
             return key; \
         }
 
index 77762f7..e9bd686 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010, 2011, 2015-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2012 Intel Corporation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -1722,7 +1722,7 @@ void WebPageProxy::setMaintainsInactiveSelection(bool newValue)
     
 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument)
 {
-    static NeverDestroyed<String> ignoreSpellingCommandName(ASCIILiteral("ignoreSpelling"));
+    static NeverDestroyed<String> ignoreSpellingCommandName(MAKE_STATIC_STRING_IMPL("ignoreSpelling"));
 
     if (!isValid())
         return;
index 195501a..c999eff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -170,21 +170,21 @@ bool WebEditorClient::shouldMoveRangeAfterDelete(Range*, Range*)
 void WebEditorClient::didBeginEditing()
 {
     // FIXME: What good is a notification name, if it's always the same?
-    static NeverDestroyed<String> WebViewDidBeginEditingNotification(ASCIILiteral("WebViewDidBeginEditingNotification"));
+    static NeverDestroyed<String> WebViewDidBeginEditingNotification(MAKE_STATIC_STRING_IMPL("WebViewDidBeginEditingNotification"));
     m_page->injectedBundleEditorClient().didBeginEditing(*m_page, WebViewDidBeginEditingNotification.get().impl());
     notImplemented();
 }
 
 void WebEditorClient::respondToChangedContents()
 {
-    static NeverDestroyed<String> WebViewDidChangeNotification(ASCIILiteral("WebViewDidChangeNotification"));
+    static NeverDestroyed<String> WebViewDidChangeNotification(MAKE_STATIC_STRING_IMPL("WebViewDidChangeNotification"));
     m_page->injectedBundleEditorClient().didChange(*m_page, WebViewDidChangeNotification.get().impl());
     notImplemented();
 }
 
 void WebEditorClient::respondToChangedSelection(Frame* frame)
 {
-    static NeverDestroyed<String> WebViewDidChangeSelectionNotification(ASCIILiteral("WebViewDidChangeSelectionNotification"));
+    static NeverDestroyed<String> WebViewDidChangeSelectionNotification(MAKE_STATIC_STRING_IMPL("WebViewDidChangeSelectionNotification"));
     m_page->injectedBundleEditorClient().didChangeSelection(*m_page, WebViewDidChangeSelectionNotification.get().impl());
     if (!frame)
         return;
@@ -218,7 +218,7 @@ void WebEditorClient::canceledComposition()
 
 void WebEditorClient::didEndEditing()
 {
-    static NeverDestroyed<String> WebViewDidEndEditingNotification(ASCIILiteral("WebViewDidEndEditingNotification"));
+    static NeverDestroyed<String> WebViewDidEndEditingNotification(MAKE_STATIC_STRING_IMPL("WebViewDidEndEditingNotification"));
     m_page->injectedBundleEditorClient().didEndEditing(*m_page, WebViewDidEndEditingNotification.get().impl());
     notImplemented();
 }
index 44c4d8a..ceda6ab 100644 (file)
@@ -1,3 +1,18 @@
+2017-05-04  Mark Lam  <mark.lam@apple.com>
+
+        NeverDestroyed<String>(ASCIILiteral(...)) is not thread safe.
+        https://bugs.webkit.org/show_bug.cgi?id=171586
+        <rdar://problem/31873190>
+
+        Reviewed by Yusuke Suzuki.
+
+        API test for exercising StaticStringImpl and the MAKE_STATIC_STRING_IMPL macro.
+
+        * TestWebKitAPI/Tests/WTF/StringImpl.cpp:
+        (TestWebKitAPI::neverDestroyedString):
+        (TestWebKitAPI::getNeverDestroyedStringAtStackDepth):
+        (TestWebKitAPI::TEST):
+
 2017-05-04  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         [WK2] Add support for keeping the selection in a focused editable element when dragging begins
index fdb701c..9652594 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 
 #include <wtf/Hasher.h>
+#include <wtf/NeverDestroyed.h>
 #include <wtf/text/SymbolImpl.h>
 #include <wtf/text/WTFString.h>
 
@@ -626,4 +627,52 @@ TEST(WTF, StringImplEmpty)
     ASSERT_FALSE(StringImpl::empty()->length());
 }
 
+static const String& neverDestroyedString()
+{
+    static NeverDestroyed<String> str(StaticStringImpl("NeverDestroyedString"));
+    return str;
+};
+
+static const String& getNeverDestroyedStringAtStackDepth(int i)
+{
+    if (--i)
+        return getNeverDestroyedStringAtStackDepth(i);
+    return neverDestroyedString();
+};
+
+TEST(WTF, StaticStringImpl)
+{
+    // Construct using MAKE_STATIC_STRING_IMPL.
+    String hello(MAKE_STATIC_STRING_IMPL("hello"));
+    String world(MAKE_STATIC_STRING_IMPL("world"));
+    String longer(MAKE_STATIC_STRING_IMPL("longer"));
+    String hello2(MAKE_STATIC_STRING_IMPL("hello"));
+
+    ASSERT_EQ(strlen("hello"), hello.length());
+    ASSERT_EQ(strlen("world"), world.length());
+    ASSERT_EQ(strlen("longer"), longer.length());
+    ASSERT_EQ(strlen("hello"), hello2.length());
+
+    ASSERT_TRUE(equal(hello, "hello"));
+    ASSERT_TRUE(equal(world, "world"));
+    ASSERT_TRUE(equal(longer, "longer"));
+    ASSERT_TRUE(equal(hello2, "hello"));
+
+    // Each StaticStringImpl* returned by MAKE_STATIC_STRING_IMPL should be unique.
+    ASSERT_NE(hello.impl(), hello2.impl());
+
+    // Test that MAKE_STATIC_STRING_IMPL isn't allocating a StaticStringImpl on the stack.
+    const String& str1 = getNeverDestroyedStringAtStackDepth(10);
+    ASSERT_EQ(strlen("NeverDestroyedString"), str1.length());
+    ASSERT_TRUE(equal(str1, "NeverDestroyedString"));
+
+    const String& str2 = getNeverDestroyedStringAtStackDepth(20);
+    ASSERT_EQ(strlen("NeverDestroyedString"), str2.length());
+    ASSERT_TRUE(equal(str2, "NeverDestroyedString"));
+
+    ASSERT_TRUE(equal(str1, str2));
+    ASSERT_EQ(&str1, &str2);
+    ASSERT_EQ(str1.impl(), str2.impl());
+}
+
 } // namespace TestWebKitAPI