JSString should remember AtomicString
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 26 Jun 2013 03:48:12 +0000 (03:48 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 26 Jun 2013 03:48:12 +0000 (03:48 +0000)
https://bugs.webkit.org/show_bug.cgi?id=117386

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Added JSValue::toAtomicString and JSString::atomicString. These two functions allow WebCore to update
JSString's m_value to set isAtomic flag and avoid the AtomicStringTable lookups in subsequent attempts
to obtain the AtomicString of the same value.

* runtime/JSCJSValue.h:
* runtime/JSString.h:
(JSC::JSString::atomicString):
(JSC::JSValue::toAtomicString):

Source/WebCore:

Added "Atomic" attribute as a WebKit extension to WebIDL, and deployed it in Element.idl and Node.idl so that
the binding code can use newly added JSValue::toAtomic to update JSString's m_value.

* bindings/js/JSDOMBinding.cpp:
(WebCore::valueToAtomicStringWithNullCheck): Added.
(WebCore::valueToAtomicStringWithUndefinedOrNullCheck): Added.

* bindings/js/JSDOMBinding.h:

* bindings/scripts/CodeGeneratorJS.pm:
(GetNativeTypeFromSignature): Return const AtomicString& when either Atomic attribute is specified or the type is
Reflect. Note that setAttribute and getAttribute both use AtomicString for all arguments.
(JSValueToNative): Use AtomicString equivalents when possible when converting DOMString to a WebCore object.

* bindings/scripts/IDLAttributes.txt: Added "Atomic" attribute.

* bindings/scripts/test/JS/JSTestObj.cpp: Baselined test cases.
(WebCore::setJSTestObjReflectedStringAttr):
(WebCore::setJSTestObjReflectedURLAttr):
(WebCore::setJSTestObjReflectedCustomURLAttr):

* dom/Document.idl:
* dom/Element.idl:
* dom/Node.idl:

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

12 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/JSCJSValue.h
Source/JavaScriptCore/runtime/JSString.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSDOMBinding.cpp
Source/WebCore/bindings/js/JSDOMBinding.h
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/IDLAttributes.txt
Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp
Source/WebCore/dom/Document.idl
Source/WebCore/dom/Element.idl
Source/WebCore/dom/Node.idl

index aa113ae..5e58d5e 100644 (file)
@@ -1,3 +1,19 @@
+2013-06-25  Ryosuke Niwa  <rniwa@webkit.org>
+
+        JSString should remember AtomicString
+        https://bugs.webkit.org/show_bug.cgi?id=117386
+
+        Reviewed by Geoffrey Garen.
+
+        Added JSValue::toAtomicString and JSString::atomicString. These two functions allow WebCore to update
+        JSString's m_value to set isAtomic flag and avoid the AtomicStringTable lookups in subsequent attempts
+        to obtain the AtomicString of the same value.
+
+        * runtime/JSCJSValue.h:
+        * runtime/JSString.h:
+        (JSC::JSString::atomicString):
+        (JSC::JSValue::toAtomicString):
+
 2013-06-24  Roger Fong  <roger_fong@apple.com>
 
         Unreviewed. Makefile build fix for AppleWindows.
index abb4b81..4997589 100644 (file)
@@ -220,6 +220,7 @@ public:
     // been set in the ExecState already.
     double toNumber(ExecState*) const;
     JSString* toString(ExecState*) const;
+    AtomicString toAtomicString(ExecState*) const;
     WTF::String toWTFString(ExecState*) const;
     WTF::String toWTFStringInline(ExecState*) const;
     JSObject* toObject(ExecState*) const;
index 855de97..d2f3a88 100644 (file)
@@ -139,6 +139,7 @@ public:
     const String& value(ExecState*) const;
     const String& tryGetValue() const;
     unsigned length() { return m_length; }
+    AtomicString atomicString(ExecState*) const;
 
     JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
     JS_EXPORT_PRIVATE bool toBoolean() const;
@@ -371,6 +372,19 @@ inline const String& JSString::value(ExecState* exec) const
     return m_value;
 }
 
+inline AtomicString JSString::atomicString(ExecState* exec) const
+{
+    if (isRope()) {
+        static_cast<const JSRopeString*>(this)->resolveRope(exec);
+        if (exec->hadException())
+            return nullAtom;
+    }
+    const AtomicString atomicValue(m_value);
+    if (atomicValue.impl() != m_value.impl())
+        m_value = atomicValue;
+    return atomicValue;
+}
+
 inline const String& JSString::tryGetValue() const
 {
     if (isRope())
@@ -516,6 +530,13 @@ inline JSString* JSValue::toString(ExecState* exec) const
     return toStringSlowCase(exec);
 }
 
+inline AtomicString JSValue::toAtomicString(ExecState* exec) const
+{
+    if (isString())
+        return jsCast<JSString*>(asCell())->atomicString(exec);
+    return toStringSlowCase(exec)->value(exec);
+}
+
 inline String JSValue::toWTFString(ExecState* exec) const
 {
     if (isString())
index 03d03c1..a29473c 100644 (file)
@@ -1,3 +1,35 @@
+2013-06-25  Ryosuke Niwa  <rniwa@webkit.org>
+
+        JSString should remember AtomicString
+        https://bugs.webkit.org/show_bug.cgi?id=117386
+
+        Reviewed by Geoffrey Garen.
+
+        Added "Atomic" attribute as a WebKit extension to WebIDL, and deployed it in Element.idl and Node.idl so that
+        the binding code can use newly added JSValue::toAtomic to update JSString's m_value.
+
+        * bindings/js/JSDOMBinding.cpp:
+        (WebCore::valueToAtomicStringWithNullCheck): Added.
+        (WebCore::valueToAtomicStringWithUndefinedOrNullCheck): Added.
+
+        * bindings/js/JSDOMBinding.h:
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GetNativeTypeFromSignature): Return const AtomicString& when either Atomic attribute is specified or the type is
+        Reflect. Note that setAttribute and getAttribute both use AtomicString for all arguments.
+        (JSValueToNative): Use AtomicString equivalents when possible when converting DOMString to a WebCore object.
+
+        * bindings/scripts/IDLAttributes.txt: Added "Atomic" attribute.
+
+        * bindings/scripts/test/JS/JSTestObj.cpp: Baselined test cases.
+        (WebCore::setJSTestObjReflectedStringAttr):
+        (WebCore::setJSTestObjReflectedURLAttr):
+        (WebCore::setJSTestObjReflectedCustomURLAttr):
+
+        * dom/Document.idl:
+        * dom/Element.idl:
+        * dom/Node.idl:
+
 2013-06-25  Kangil Han  <kangil.han@samsung.com>
 
         Adopt is/toHTMLAnchorElement for code cleanup
index 2462cf5..2eb66d7 100644 (file)
@@ -109,6 +109,13 @@ String valueToStringWithNullCheck(ExecState* exec, JSValue value)
     return value.toString(exec)->value(exec);
 }
 
+AtomicString valueToAtomicStringWithNullCheck(ExecState* exec, JSValue value)
+{
+    if (value.isNull())
+        return nullAtom;
+    return value.toAtomicString(exec);
+}
+
 String valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value)
 {
     if (value.isUndefinedOrNull())
@@ -116,6 +123,13 @@ String valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value)
     return value.toString(exec)->value(exec);
 }
 
+AtomicString valueToAtomicStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value)
+{
+    if (value.isUndefinedOrNull())
+        return nullAtom;
+    return value.toAtomicString(exec);
+}
+
 JSValue jsDateOrNull(ExecState* exec, double value)
 {
     if (!std::isfinite(value))
index 92eccb4..f813c0a 100644 (file)
@@ -249,7 +249,10 @@ class DOMStringList;
     AtomicStringImpl* findAtomicString(JSC::PropertyName);
 
     String valueToStringWithNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null
+    AtomicString valueToAtomicStringWithNullCheck(JSC::ExecState*, JSC::JSValue);
+
     String valueToStringWithUndefinedOrNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null or undefined
+    AtomicString valueToAtomicStringWithUndefinedOrNullCheck(JSC::ExecState*, JSC::JSValue);
 
     inline int32_t finiteInt32Value(JSC::JSValue value, JSC::ExecState* exec, bool& okay)
     {
index 12d45ce..349b8d6 100644 (file)
@@ -3362,6 +3362,11 @@ sub GetNativeTypeFromSignature
         return "int";
     }
 
+    # FIXME: GetNativeType should support Atomic extension.
+    if ($type eq "DOMString" and ($signature->extendedAttributes->{"Atomic"} or $signature->extendedAttributes->{"Reflect"})) {
+        return "const AtomicString&";
+    }
+
     return GetNativeType($type);
 }
 
@@ -3501,11 +3506,22 @@ sub JSValueToNative
     if ($type eq "DOMString") {
         # FIXME: This implements [TreatNullAs=NullString] and [TreatUndefinedAs=NullString],
         # but the Web IDL spec requires [TreatNullAs=EmptyString] and [TreatUndefinedAs=EmptyString].
-        if (($signature->extendedAttributes->{"TreatNullAs"} and $signature->extendedAttributes->{"TreatNullAs"} eq "NullString") and ($signature->extendedAttributes->{"TreatUndefinedAs"} and $signature->extendedAttributes->{"TreatUndefinedAs"} eq "NullString")) {
-            return "valueToStringWithUndefinedOrNullCheck(exec, $value)"
+        if (($signature->extendedAttributes->{"TreatNullAs"} and $signature->extendedAttributes->{"TreatNullAs"} eq "NullString")
+            and ($signature->extendedAttributes->{"TreatUndefinedAs"} and $signature->extendedAttributes->{"TreatUndefinedAs"} eq "NullString")) {
+            if ($signature->extendedAttributes->{"Atomic"}) {
+                return "valueToStringWithUndefinedOrNullCheck(exec, $value)";
+            } else {
+                return "valueToAtomicStringWithUndefinedOrNullCheck(exec, $value)";
+            }
+        }
+        if ($signature->extendedAttributes->{"Reflect"}) {
+            return "valueToAtomicStringWithNullCheck(exec, $value)";
+        }
+        if ($signature->extendedAttributes->{"TreatNullAs"} and $signature->extendedAttributes->{"TreatNullAs"} eq "NullString") {
+            return "valueToStringWithNullCheck(exec, $value)";
         }
-        if (($signature->extendedAttributes->{"TreatNullAs"} and $signature->extendedAttributes->{"TreatNullAs"} eq "NullString") or $signature->extendedAttributes->{"Reflect"}) {
-            return "valueToStringWithNullCheck(exec, $value)"
+        if ($signature->extendedAttributes->{"Atomic"}) {
+            return "$value.isEmpty() ? nullAtom : $value.toAtomicString(exec)";
         }
         # FIXME: Add the case for 'if ($signature->extendedAttributes->{"TreatUndefinedAs"} and $signature->extendedAttributes->{"TreatUndefinedAs"} eq "NullString"))'.
         return "$value.isEmpty() ? String() : $value.toString(exec)->value(exec)";
index 4259007..44c2f25 100644 (file)
@@ -19,6 +19,7 @@
 #
 
 ActiveDOMObject
+Atomic
 CPPPureInterface
 CachedAttribute
 CallWith=ScriptExecutionContext|ScriptState|ScriptArguments|CallStack
index a368577..51b5f55 100644 (file)
@@ -1278,7 +1278,7 @@ void setJSTestObjReflectedStringAttr(ExecState* exec, JSObject* thisObject, JSVa
     UNUSED_PARAM(exec);
     JSTestObj* castedThis = jsCast<JSTestObj*>(thisObject);
     TestObj* impl = static_cast<TestObj*>(castedThis->impl());
-    const String& nativeValue(valueToStringWithNullCheck(exec, value));
+    const AtomicString& nativeValue(valueToAtomicStringWithNullCheck(exec, value));
     if (exec->hadException())
         return;
     impl->setAttribute(WebCore::HTMLNames::reflectedstringattrAttr, nativeValue);
@@ -1326,7 +1326,7 @@ void setJSTestObjReflectedURLAttr(ExecState* exec, JSObject* thisObject, JSValue
     UNUSED_PARAM(exec);
     JSTestObj* castedThis = jsCast<JSTestObj*>(thisObject);
     TestObj* impl = static_cast<TestObj*>(castedThis->impl());
-    const String& nativeValue(valueToStringWithNullCheck(exec, value));
+    const AtomicString& nativeValue(valueToAtomicStringWithNullCheck(exec, value));
     if (exec->hadException())
         return;
     impl->setAttribute(WebCore::HTMLNames::reflectedurlattrAttr, nativeValue);
@@ -1338,7 +1338,7 @@ void setJSTestObjReflectedStringAttr(ExecState* exec, JSObject* thisObject, JSVa
     UNUSED_PARAM(exec);
     JSTestObj* castedThis = jsCast<JSTestObj*>(thisObject);
     TestObj* impl = static_cast<TestObj*>(castedThis->impl());
-    const String& nativeValue(valueToStringWithNullCheck(exec, value));
+    const AtomicString& nativeValue(valueToAtomicStringWithNullCheck(exec, value));
     if (exec->hadException())
         return;
     impl->setAttribute(WebCore::HTMLNames::customContentStringAttrAttr, nativeValue);
@@ -1374,7 +1374,7 @@ void setJSTestObjReflectedCustomURLAttr(ExecState* exec, JSObject* thisObject, J
     UNUSED_PARAM(exec);
     JSTestObj* castedThis = jsCast<JSTestObj*>(thisObject);
     TestObj* impl = static_cast<TestObj*>(castedThis->impl());
-    const String& nativeValue(valueToStringWithNullCheck(exec, value));
+    const AtomicString& nativeValue(valueToAtomicStringWithNullCheck(exec, value));
     if (exec->hadException())
         return;
     impl->setAttribute(WebCore::HTMLNames::customContentURLAttrAttr, nativeValue);
index f065abd..44fd5cc 100644 (file)
@@ -29,7 +29,7 @@
     readonly attribute DOMImplementation implementation;
     readonly attribute Element documentElement;
 
-    [ReturnNewObject, RaisesException] Element createElement([TreatNullAs=NullString,Default=Undefined] optional DOMString tagName);
+    [ReturnNewObject, RaisesException] Element createElement([TreatNullAs=NullString,Default=Undefined,Atomic] optional DOMString tagName);
     DocumentFragment   createDocumentFragment();
     [ReturnNewObject] Text createTextNode([Default=Undefined] optional DOMString data);
     [ReturnNewObject] Comment createComment([Default=Undefined] optional DOMString data);
@@ -38,7 +38,7 @@
                                                                                  [Default=Undefined] optional DOMString data);
     [ReturnNewObject, RaisesException] Attr createAttribute([Default=Undefined] optional DOMString name);
     [ReturnNewObject, RaisesException] EntityReference createEntityReference([Default=Undefined] optional DOMString name);
-    NodeList getElementsByTagName([Default=Undefined] optional DOMString tagname);
+    NodeList getElementsByTagName([Default=Undefined, Atomic] optional DOMString tagname);
 
     // Introduced in DOM Level 2:
 
@@ -48,9 +48,9 @@
                             [TreatNullAs=NullString,Default=Undefined] optional DOMString qualifiedName);
     [ObjCLegacyUnnamedParameters, ReturnNewObject, RaisesException] Attr createAttributeNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
                                                                           [TreatNullAs=NullString,Default=Undefined] optional DOMString qualifiedName);
-    [ObjCLegacyUnnamedParameters] NodeList getElementsByTagNameNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
-                                                   [Default=Undefined] optional DOMString localName);
-    Element getElementById([Default=Undefined] optional DOMString elementId);
+    [ObjCLegacyUnnamedParameters] NodeList getElementsByTagNameNS([TreatNullAs=NullString,Default=Undefined,Atomic] optional DOMString namespaceURI,
+                                                   [Default=Undefined,Atomic] optional DOMString localName);
+    Element getElementById([Default=Undefined,Atomic] optional DOMString elementId);
 
     // DOM Level 3 Core
 
     readonly attribute DOMString compatMode;
 
     // NodeSelector - Selector API
-    [RaisesException] Element querySelector(DOMString selectors);
-    [RaisesException] NodeList querySelectorAll(DOMString selectors);
+    [RaisesException] Element querySelector([Atomic] DOMString selectors);
+    [RaisesException] NodeList querySelectorAll([Atomic] DOMString selectors);
 
 #if defined(ENABLE_FULLSCREEN_API) && ENABLE_FULLSCREEN_API
     // Mozilla version
 
 #if defined(ENABLE_CUSTOM_ELEMENTS) && ENABLE_CUSTOM_ELEMENTS
     [Conditional=CUSTOM_ELEMENTS, ImplementedAs=registerElement, CallWith=ScriptState, RaisesException] CustomElementConstructor webkitRegister(DOMString name, optional Dictionary options);
-    [ReturnNewObject, RaisesException] Element createElement(DOMString localName, [TreatNullAs=NullString] DOMString typeExtension);
-    [ReturnNewObject, RaisesException] Element createElementNS([TreatNullAs=NullString] DOMString namespaceURI, DOMString qualifiedName,
-                            [TreatNullAs=NullString] DOMString typeExtension);
+    [ReturnNewObject, RaisesException] Element createElement([Atomic] DOMString localName, [TreatNullAs=NullString, Atomic] DOMString typeExtension);
+    [ReturnNewObject, RaisesException] Element createElementNS([TreatNullAs=NullString, Atomic] DOMString namespaceURI, DOMString qualifiedName,
+                            [TreatNullAs=NullString, Atomic] DOMString typeExtension);
 #endif
 
 #if defined(LANGUAGE_CPP) && LANGUAGE_CPP
index 22e4610..9c8a437 100644 (file)
 
     [TreatReturnedNullStringAs=Null] readonly attribute DOMString tagName;
 
-    [TreatReturnedNullStringAs=Null] DOMString getAttribute([Default=Undefined] optional DOMString name);
-    [ObjCLegacyUnnamedParameters, RaisesException] void setAttribute([Default=Undefined] optional DOMString name,
-                                     [Default=Undefined] optional DOMString value);
-    void removeAttribute([Default=Undefined] optional DOMString name);
-    Attr getAttributeNode([Default=Undefined] optional DOMString name);
+    [TreatReturnedNullStringAs=Null] DOMString getAttribute([Default=Undefined, Atomic] optional DOMString name);
+    [ObjCLegacyUnnamedParameters, RaisesException] void setAttribute([Default=Undefined, Atomic] optional DOMString name,
+                                     [Default=Undefined, Atomic] optional DOMString value);
+    void removeAttribute([Default=Undefined, Atomic] optional DOMString name);
+    Attr getAttributeNode([Default=Undefined, Atomic] optional DOMString name);
     [RaisesException] Attr setAttributeNode([Default=Undefined] optional Attr newAttr);
     [RaisesException] Attr removeAttributeNode([Default=Undefined] optional Attr oldAttr);
-    NodeList getElementsByTagName([Default=Undefined] optional DOMString name);
+    NodeList getElementsByTagName([Default=Undefined, Atomic] optional DOMString name);
 
 #if !defined(LANGUAGE_OBJECTIVE_C)
     // For ObjC this is defined on Node for legacy support.
 
     // DOM Level 2 Core
 
-    [ObjCLegacyUnnamedParameters] DOMString getAttributeNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
-                                            [Default=Undefined] optional DOMString localName);
-    [ObjCLegacyUnnamedParameters, RaisesException] void setAttributeNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
-                                       [Default=Undefined] optional DOMString qualifiedName, 
-                                       [Default=Undefined] optional DOMString value);
-    [ObjCLegacyUnnamedParameters] void removeAttributeNS([TreatNullAs=NullString] DOMString namespaceURI,
-                                          DOMString localName);
-    [ObjCLegacyUnnamedParameters] NodeList getElementsByTagNameNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
-                                                   [Default=Undefined] optional DOMString localName);
-    [ObjCLegacyUnnamedParameters] Attr getAttributeNodeNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
-                                           [Default=Undefined] optional DOMString localName);
+    [ObjCLegacyUnnamedParameters] DOMString getAttributeNS([TreatNullAs=NullString, Default=Undefined, Atomic] optional DOMString namespaceURI,
+                                            [Default=Undefined, Atomic] optional DOMString localName);
+    [ObjCLegacyUnnamedParameters, RaisesException] void setAttributeNS([TreatNullAs=NullString, Default=Undefined, Atomic] optional DOMString namespaceURI,
+                                       [Default=Undefined, Atomic] optional DOMString qualifiedName, 
+                                       [Default=Undefined, Atomic] optional DOMString value);
+    [ObjCLegacyUnnamedParameters] void removeAttributeNS([TreatNullAs=NullString, Atomic] DOMString namespaceURI,
+                                          [Atomic] DOMString localName);
+    [ObjCLegacyUnnamedParameters] NodeList getElementsByTagNameNS([TreatNullAs=NullString, Default=Undefined, Atomic] optional DOMString namespaceURI,
+                                                   [Default=Undefined, Atomic] optional DOMString localName);
+    [ObjCLegacyUnnamedParameters] Attr getAttributeNodeNS([TreatNullAs=NullString, Default=Undefined, Atomic] optional DOMString namespaceURI,
+                                           [Default=Undefined, Atomic] optional DOMString localName);
     [RaisesException] Attr setAttributeNodeNS([Default=Undefined] optional Attr newAttr);
     boolean hasAttribute(DOMString name);
-    [ObjCLegacyUnnamedParameters] boolean hasAttributeNS([TreatNullAs=NullString,Default=Undefined] optional DOMString namespaceURI,
-                                          [Default=Undefined] optional DOMString localName);
+    [ObjCLegacyUnnamedParameters] boolean hasAttributeNS([TreatNullAs=NullString, Default=Undefined, Atomic] optional DOMString namespaceURI,
+                                          [Default=Undefined, Atomic] optional DOMString localName);
 
     readonly attribute CSSStyleDeclaration style;
 
@@ -99,8 +99,8 @@
 #endif
 
     // NodeSelector - Selector API
-    [RaisesException] Element querySelector(DOMString selectors);
-    [RaisesException] NodeList querySelectorAll(DOMString selectors);
+    [RaisesException] Element querySelector([Atomic] DOMString selectors);
+    [RaisesException] NodeList querySelectorAll([Atomic] DOMString selectors);
 
     // WebKit extension, pending specification.
     [RaisesException] boolean webkitMatchesSelector([Default=Undefined] optional DOMString selectors);
index 8626bc3..7e42d5c 100644 (file)
 
 #if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP
 #if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C
-    void addEventListener(DOMString type, 
+    void addEventListener([Atomic] DOMString type, 
                           EventListener listener, 
                           optional boolean useCapture);
-    void removeEventListener(DOMString type, 
+    void removeEventListener([Atomic] DOMString type, 
                              EventListener listener, 
                              optional boolean useCapture);
     [RaisesException] boolean dispatchEvent(Event event);