Support latest Web IDL named property getters
authorch.dumez@sisa.samsung.com <ch.dumez@sisa.samsung.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Jun 2013 13:04:10 +0000 (13:04 +0000)
committerch.dumez@sisa.samsung.com <ch.dumez@sisa.samsung.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Jun 2013 13:04:10 +0000 (13:04 +0000)
https://bugs.webkit.org/show_bug.cgi?id=117403

Reviewed by Kentaro Hara.

Add support for the latest Web IDL named property getters to the JSC
bindings generator:
http://www.w3.org/TR/WebIDL/#idl-named-properties

Drop support for outdated [NamedGetter] IDL extended attribute.

Support for other kinds of named properties will be added in later
patches. This patch only brings named property getters.

This patch is based on Blink r149247 by kojih@chromium.org.

No new tests, no behavior change.

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateGetOwnPropertySlotBody):
(GenerateGetOwnPropertyDescriptorBody):
(GetSpecialAccessorFunctionForType):
(GetNamedGetterFunction):
(GenerateHeader):
(GenerateImplementation):
* bindings/scripts/IDLAttributes.txt:
* bindings/scripts/IDLParser.pm:
(applyTypedefs):
(parseSpecialOperation):
(parseSpecials):
(applyMemberList):
* bindings/scripts/test/TestEventTarget.idl:
* css/StyleSheetList.idl:
* dom/DOMNamedFlowCollection.idl:
* dom/DOMStringMap.idl:
* dom/NamedNodeMap.idl:
* dom/NodeList.idl:
* html/HTMLAllCollection.idl:
* html/HTMLCollection.idl:
* html/HTMLFormControlsCollection.idl:
* html/HTMLPropertiesCollection.idl:
* plugins/DOMMimeTypeArray.idl:
* plugins/DOMPlugin.idl:
* plugins/DOMPluginArray.idl:
* storage/Storage.idl:

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

18 files changed:
Source/WebCore/ChangeLog
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/IDLAttributes.txt
Source/WebCore/bindings/scripts/IDLParser.pm
Source/WebCore/bindings/scripts/test/TestEventTarget.idl
Source/WebCore/css/StyleSheetList.idl
Source/WebCore/dom/DOMNamedFlowCollection.idl
Source/WebCore/dom/DOMStringMap.idl
Source/WebCore/dom/NamedNodeMap.idl
Source/WebCore/dom/NodeList.idl
Source/WebCore/html/HTMLAllCollection.idl
Source/WebCore/html/HTMLCollection.idl
Source/WebCore/html/HTMLFormControlsCollection.idl
Source/WebCore/html/HTMLPropertiesCollection.idl
Source/WebCore/plugins/DOMMimeTypeArray.idl
Source/WebCore/plugins/DOMPlugin.idl
Source/WebCore/plugins/DOMPluginArray.idl
Source/WebCore/storage/Storage.idl

index 8447aa6..7f0d606 100644 (file)
@@ -1,3 +1,51 @@
+2013-06-11  Christophe Dumez  <ch.dumez@sisa.samsung.com>
+
+        Support latest Web IDL named property getters
+        https://bugs.webkit.org/show_bug.cgi?id=117403
+
+        Reviewed by Kentaro Hara.
+
+        Add support for the latest Web IDL named property getters to the JSC
+        bindings generator:
+        http://www.w3.org/TR/WebIDL/#idl-named-properties
+
+        Drop support for outdated [NamedGetter] IDL extended attribute.
+
+        Support for other kinds of named properties will be added in later
+        patches. This patch only brings named property getters.
+
+        This patch is based on Blink r149247 by kojih@chromium.org.
+
+        No new tests, no behavior change.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateGetOwnPropertySlotBody):
+        (GenerateGetOwnPropertyDescriptorBody):
+        (GetSpecialAccessorFunctionForType):
+        (GetNamedGetterFunction):
+        (GenerateHeader):
+        (GenerateImplementation):
+        * bindings/scripts/IDLAttributes.txt:
+        * bindings/scripts/IDLParser.pm:
+        (applyTypedefs):
+        (parseSpecialOperation):
+        (parseSpecials):
+        (applyMemberList):
+        * bindings/scripts/test/TestEventTarget.idl:
+        * css/StyleSheetList.idl:
+        * dom/DOMNamedFlowCollection.idl:
+        * dom/DOMStringMap.idl:
+        * dom/NamedNodeMap.idl:
+        * dom/NodeList.idl:
+        * html/HTMLAllCollection.idl:
+        * html/HTMLCollection.idl:
+        * html/HTMLFormControlsCollection.idl:
+        * html/HTMLPropertiesCollection.idl:
+        * plugins/DOMMimeTypeArray.idl:
+        * plugins/DOMPlugin.idl:
+        * plugins/DOMPluginArray.idl:
+        * storage/Storage.idl:
+
 2013-06-11  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [BlackBerry] Test editing/execCommand/indent-paragraphs.html times out
index e2d9365..34bac35 100644 (file)
@@ -352,6 +352,7 @@ sub GenerateGetOwnPropertySlotBody
     my ($interface, $interfaceName, $className, $hasAttributes, $inlined) = @_;
 
     my $namespaceMaybe = ($inlined ? "JSC::" : "");
+    my $namedGetterFunction = GetNamedGetterFunction($interface);
 
     my @getOwnPropertySlotImpl = ();
 
@@ -362,7 +363,7 @@ sub GenerateGetOwnPropertySlotBody
     }
 
     my $manualLookupGetterGeneration = sub {
-        my $requiresManualLookup = $interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"NamedGetter"};
+        my $requiresManualLookup = $interface->extendedAttributes->{"IndexedGetter"} || $namedGetterFunction;
         if ($requiresManualLookup) {
             push(@getOwnPropertySlotImpl, "    const ${namespaceMaybe}HashEntry* entry = getStaticValueSlotEntryWithoutCaching<$className>(exec, propertyName);\n");
             push(@getOwnPropertySlotImpl, "    if (entry) {\n");
@@ -395,7 +396,7 @@ sub GenerateGetOwnPropertySlotBody
         push(@getOwnPropertySlotImpl, "    }\n");
     }
 
-    if ($interface->extendedAttributes->{"NamedGetter"} || $interface->extendedAttributes->{"CustomNamedGetter"}) {
+    if ($namedGetterFunction || $interface->extendedAttributes->{"CustomNamedGetter"}) {
         push(@getOwnPropertySlotImpl, "    if (canGetItemsForName(exec, static_cast<$interfaceName*>(thisObject->impl()), propertyName)) {\n");
         push(@getOwnPropertySlotImpl, "        slot.setCustom(thisObject, thisObject->nameGetter);\n");
         push(@getOwnPropertySlotImpl, "        return true;\n");
@@ -435,6 +436,7 @@ sub GenerateGetOwnPropertyDescriptorBody
     my ($interface, $interfaceName, $className, $hasAttributes, $inlined) = @_;
     
     my $namespaceMaybe = ($inlined ? "JSC::" : "");
+    my $namedGetterFunction = GetNamedGetterFunction($interface);
     
     my @getOwnPropertyDescriptorImpl = ();
     if ($interface->extendedAttributes->{"CheckSecurity"}) {
@@ -454,7 +456,7 @@ sub GenerateGetOwnPropertyDescriptorBody
     }
     
     my $manualLookupGetterGeneration = sub {
-        my $requiresManualLookup = $interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"NamedGetter"};
+        my $requiresManualLookup = $interface->extendedAttributes->{"IndexedGetter"} || $namedGetterFunction;
         if ($requiresManualLookup) {
             push(@getOwnPropertyDescriptorImpl, "    const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");
             push(@getOwnPropertyDescriptorImpl, "    if (entry) {\n");
@@ -494,7 +496,7 @@ sub GenerateGetOwnPropertyDescriptorBody
         push(@getOwnPropertyDescriptorImpl, "    }\n");
     }
 
-    if ($interface->extendedAttributes->{"NamedGetter"} || $interface->extendedAttributes->{"CustomNamedGetter"}) {
+    if ($namedGetterFunction || $interface->extendedAttributes->{"CustomNamedGetter"}) {
         push(@getOwnPropertyDescriptorImpl, "    if (canGetItemsForName(exec, static_cast<$interfaceName*>(thisObject->impl()), propertyName)) {\n");
         push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\n");
         push(@getOwnPropertyDescriptorImpl, "        slot.setCustom(thisObject, nameGetter);\n");
@@ -611,6 +613,31 @@ sub GetFunctionName
     return $codeGenerator->WK_lcfirst($className) . $kind . "Function" . $codeGenerator->WK_ucfirst($function->signature->name);
 }
 
+sub GetSpecialAccessorFunctionForType
+{
+    my $interface = shift;
+    my $special = shift;
+    my $firstParameterType = shift;
+    my $numberOfParameters = shift;
+
+    foreach my $function (@{$interface->functions}, @{$interface->anonymousFunctions}) {
+        my $specials = $function->signature->specials;
+        my $specialExists = grep { $_ eq $special } @$specials;
+        my $parameters = $function->parameters;
+        if ($specialExists and scalar(@$parameters) == $numberOfParameters and $parameters->[0]->type eq $firstParameterType) {
+            return $function;
+        }
+    }
+
+    return 0;
+}
+
+sub GetNamedGetterFunction
+{
+    my $interface = shift;
+    return GetSpecialAccessorFunctionForType($interface, "getter", "DOMString", 1);
+}
+
 sub GenerateHeader
 {
     my $object = shift;
@@ -745,8 +772,10 @@ sub GenerateHeader
 
     $implIncludes{"${className}Custom.h"} = 1 if !$interface->extendedAttributes->{"JSCustomHeader"} && ($interface->extendedAttributes->{"CustomPutFunction"} || $interface->extendedAttributes->{"CustomNamedSetter"});
 
+    my $namedGetterFunction = GetNamedGetterFunction($interface);
+
     my $hasImpureNamedGetter =
-        $interface->extendedAttributes->{"NamedGetter"}
+        $namedGetterFunction
         || $interface->extendedAttributes->{"CustomNamedGetter"}
         || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
 
@@ -983,7 +1012,7 @@ sub GenerateHeader
         push(@headerContent, "    void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\n");
     }
     # Name getter
-    if ($interface->extendedAttributes->{"NamedGetter"} || $interface->extendedAttributes->{"CustomNamedGetter"}) {
+    if ($namedGetterFunction || $interface->extendedAttributes->{"CustomNamedGetter"}) {
         push(@headerContent, "private:\n");
         push(@headerContent, "    static bool canGetItemsForName(JSC::ExecState*, $interfaceName*, JSC::PropertyName);\n");
         push(@headerContent, "    static JSC::JSValue nameGetter(JSC::ExecState*, JSC::JSValue, JSC::PropertyName);\n");
@@ -1577,6 +1606,8 @@ sub GenerateImplementation
     my $numConstants = @{$interface->constants};
     my $numFunctions = @{$interface->functions};
 
+    my $namedGetterFunction = GetNamedGetterFunction($interface);
+
     # - Add all constants
     if (!$interface->extendedAttributes->{"NoInterfaceObject"}) {
         my $hashSize = $numConstants;
@@ -1892,7 +1923,7 @@ sub GenerateImplementation
                  || $interface->extendedAttributes->{"NumericIndexedGetter"}
                  || $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}
                  || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"}
-                 || $interface->extendedAttributes->{"NamedGetter"}
+                 || $namedGetterFunction
                  || $interface->extendedAttributes->{"CustomNamedGetter"};
 
     # Attributes
@@ -1913,7 +1944,7 @@ sub GenerateImplementation
         }
 
         if ($interface->extendedAttributes->{"IndexedGetter"} || $interface->extendedAttributes->{"NumericIndexedGetter"}
-                || $interface->extendedAttributes->{"NamedGetter"} || $interface->extendedAttributes->{"CustomNamedGetter"}
+                || $namedGetterFunction || $interface->extendedAttributes->{"CustomNamedGetter"}
                 || $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}) {
             push(@implContent, "bool ${className}::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned index, PropertySlot& slot)\n");
             push(@implContent, "{\n");
@@ -1946,7 +1977,7 @@ sub GenerateImplementation
                 push(@implContent, "    }\n");
             }
 
-            if ($interface->extendedAttributes->{"NamedGetter"} || $interface->extendedAttributes->{"CustomNamedGetter"}) {
+            if ($namedGetterFunction || $interface->extendedAttributes->{"CustomNamedGetter"}) {
                 &$propertyNameGeneration();
                 push(@implContent, "    if (canGetItemsForName(exec, static_cast<$interfaceName*>(thisObject->impl()), propertyName)) {\n");
                 push(@implContent, "        slot.setCustom(thisObject, thisObject->nameGetter);\n");
@@ -2633,7 +2664,7 @@ sub GenerateImplementation
     }
 
     if ($interfaceName eq "HTMLPropertiesCollection" or $interfaceName eq "DOMNamedFlowCollection") {
-        if ($interface->extendedAttributes->{"NamedGetter"}) {
+        if ($namedGetterFunction) {
             push(@implContent, "bool ${className}::canGetItemsForName(ExecState*, $interfaceName* collection, PropertyName propertyName)\n");
             push(@implContent, "{\n");
             push(@implContent, "    return collection->hasNamedItem(propertyNameToAtomicString(propertyName));\n");
index a0b9b7e..d411c81 100644 (file)
@@ -83,7 +83,6 @@ JSNoStaticTables
 JSWindowEventListener
 MasqueradesAsUndefined
 NamedConstructor=*
-NamedGetter
 NoInterfaceObject
 NotEnumerable
 NumericIndexedGetter
index 59d1e3b..b6daf2d 100644 (file)
@@ -46,6 +46,7 @@ struct( domInterface => {
     parents => '@',      # List of strings
     constants => '@',    # List of 'domConstant'
     functions => '@',    # List of 'domFunction'
+    anonymousFunctions => '@', # List of 'domFunction'
     attributes => '@',    # List of 'domAttribute'    
     extendedAttributes => '$', # Extended attributes
     constructors => '@', # Constructors, list of 'domFunction'
@@ -75,6 +76,7 @@ struct( domSignature => {
     direction => '$', # Variable direction (in or out)
     name => '$',      # Variable name
     type => '$',      # Variable type
+    specials => '@',  # Specials
     extendedAttributes => '$', # Extended attributes
     isNullable => '$', # Is variable type Nullable (T?)
     isVariadic => '$', # Is variable variadic (long... numbers)
@@ -378,7 +380,7 @@ sub applyTypedefs
             foreach my $attribute (@{$definition->attributes}) {
                 $self->applyTypedefsForSignature($attribute->signature);
             }
-            foreach my $function (@{$definition->functions}, @{$definition->constructors}, @{$definition->customConstructors}) {
+            foreach my $function (@{$definition->functions}, @{$definition->anonymousFunctions}, @{$definition->constructors}, @{$definition->customConstructors}) {
                 $self->applyTypedefsForSignature($function->signature);
                 foreach my $signature (@{$function->parameters}) {
                     $self->applyTypedefsForSignature($signature);
@@ -1217,12 +1219,13 @@ sub parseSpecialOperation
 
     my $next = $self->nextToken();
     if ($next->value() =~ /$nextSpecials_1/) {
-        $self->parseSpecial();
-        $self->parseSpecials();
+        my @specials = ();
+        push(@specials, @{$self->parseSpecials()});
         my $returnType = $self->parseReturnType();
         my $interface = $self->parseOperationRest($extendedAttributeList);
         if (defined ($interface)) {
             $interface->signature->type($returnType);
+             $interface->signature->specials(\@specials);
         }
         return $interface;
     }
@@ -1232,16 +1235,17 @@ sub parseSpecialOperation
 sub parseSpecials
 {
     my $self = shift;
+    my @specials = ();
 
     while (1) {
         my $next = $self->nextToken();
         if ($next->value() =~ /$nextSpecials_1/) {
-            $self->parseSpecial();
+            push(@specials, $self->parseSpecial());
         } else {
             last;
         }
     }
-    return [];
+    return \@specials;
 }
 
 sub parseSpecial
@@ -2415,7 +2419,11 @@ sub applyMemberList
             next;
         }
         if (ref($item) eq "domFunction") {
-            push(@{$interface->functions}, $item);
+            if ($item->signature->name eq "") {
+                push(@{$interface->anonymousFunctions}, $item);
+            } else {
+                push(@{$interface->functions}, $item);
+            }
             next;
         }
     }
index 6e9487e..6f06577 100644 (file)
 [
     EventTarget,
     IndexedGetter,
-    NamedGetter,
     MasqueradesAsUndefined
 ] interface TestEventTarget {
 
     Node item([IsIndex] unsigned long index);
+    getter Node (DOMString name);
 
     void addEventListener(DOMString type, 
                           EventListener listener, 
index c5d9a98..46686c1 100644 (file)
 [
     GenerateIsReachable=ImplDocument,
     IndexedGetter,
-    NamedGetter,
     ImplementationLacksVTable
 ] interface StyleSheetList {
     readonly attribute unsigned long    length;
     StyleSheet         item([Default=Undefined] optional unsigned long index);
+    getter CSSStyleSheet (DOMString name);
 };
 
index 0459683..9b43ba1 100644 (file)
     InterfaceName=WebKitNamedFlowCollection,
     JSGenerateToJSObject,
     IndexedGetter,
-    NamedGetter,
     ImplementationLacksVTable
 ] interface DOMNamedFlowCollection {
     readonly attribute unsigned long length;
     WebKitNamedFlow item(unsigned long index);
-    WebKitNamedFlow namedItem(DOMString name);
+    getter WebKitNamedFlow namedItem(DOMString name);
 };
index fdb4047..21f5bcb 100644 (file)
 
 [
     GenerateIsReachable=ImplElementRoot,
-    NamedGetter,
     CustomDeleteProperty,
     CustomEnumerateProperty,
     CustomNamedSetter,
     SkipVTableValidation
 ] interface DOMStringMap {
+    getter DOMString (DOMString name);
 };
 
index efae715..5cde88d 100644 (file)
 [
     GenerateIsReachable=ImplElementRoot,
     IndexedGetter,
-    NamedGetter,
     ImplementationLacksVTable
 ] interface NamedNodeMap {
 
-    Node getNamedItem([Default=Undefined] optional DOMString name);
+    getter Node getNamedItem([Default=Undefined] optional DOMString name);
 
     [RaisesException] Node setNamedItem([Default=Undefined] optional Node node);
 
index bdc3d35..2ffcc6e 100644 (file)
 [
     CustomIsReachable,
     IndexedGetter,
-    NamedGetter,
     SkipVTableValidation
 ] interface NodeList {
 
     Node item([IsIndex,Default=Undefined] optional unsigned long index);
+    getter (Node or unsigned long) (DOMString name);
 
     readonly attribute unsigned long length;
 
index 96f6fac..62e913e 100644 (file)
 
 [
     IndexedGetter,
-    NamedGetter,
     CustomCall,
     MasqueradesAsUndefined,
     GenerateIsReachable=ImplOwnerNodeRoot,
 ] interface HTMLAllCollection {
     readonly attribute unsigned long length;
     [Custom] Node item([Default=Undefined] optional unsigned long index);
-    [Custom] Node namedItem(DOMString name);
+    [Custom] getter Node namedItem(DOMString name);
     // FIXME: This should return an HTMLAllCollection.
     NodeList tags(DOMString name);
 };
index 2686edd..716f42b 100644 (file)
 
 [
     IndexedGetter,
-    NamedGetter,
     CustomToJSObject,
     GenerateIsReachable=ImplOwnerNodeRoot,
     ObjCPolymorphic,
 ] interface HTMLCollection {
     readonly attribute unsigned long length;
     Node item([Default=Undefined] optional unsigned long index);
-    Node namedItem([Default=Undefined] optional DOMString name);
+    getter Node namedItem([Default=Undefined] optional DOMString name);
 
 #if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C
     NodeList tags([Default=Undefined] optional DOMString name);
index 8dfa452..0c0494e 100644 (file)
@@ -20,8 +20,7 @@
 
 [
     IndexedGetter,
-    NamedGetter,
     GenerateIsReachable=ImplOwnerNodeRoot,
 ] interface HTMLFormControlsCollection : HTMLCollection {
-    [Custom] Node namedItem([Default=Undefined] optional DOMString name);
+    [Custom] getter Node namedItem([Default=Undefined] optional DOMString name);
 };
index d06bc39..49af4ef 100644 (file)
 [
     Conditional=MICRODATA,
     JSGenerateToJSObject,
-    IndexedGetter,
-    NamedGetter
+    IndexedGetter
 ] interface HTMLPropertiesCollection : HTMLCollection {
     readonly attribute unsigned long length;
     Node item(unsigned long index);
 
     readonly attribute DOMStringList names;
-    [ImplementedAs=propertyNodeList] PropertyNodeList namedItem(DOMString name);
+    [ImplementedAs=propertyNodeList] getter PropertyNodeList namedItem(DOMString name);
 };
index dc79b61..4667344 100644 (file)
 
 [
     GenerateIsReachable=ImplFrame,
-    NamedGetter,
     IndexedGetter,
     InterfaceName=MimeTypeArray
 ] interface DOMMimeTypeArray {
     readonly attribute unsigned long length;
     DOMMimeType item([Default=Undefined] optional unsigned long index);
-    DOMMimeType namedItem([Default=Undefined] optional DOMString name);
+    getter DOMMimeType namedItem([Default=Undefined] optional DOMString name);
 };
 
index 33ae079..f4ac45c 100644 (file)
@@ -19,7 +19,6 @@
 */
 
 [
-    NamedGetter,
     IndexedGetter,
     InterfaceName=Plugin
 ] interface DOMPlugin {
@@ -28,6 +27,6 @@
     readonly attribute DOMString description;
     readonly attribute unsigned long length;
     DOMMimeType item([Default=Undefined] optional unsigned long index);
-    DOMMimeType namedItem([Default=Undefined] optional DOMString name);
+    getter DOMMimeType namedItem([Default=Undefined] optional DOMString name);
 };
 
index 856cddb..b5a0fa3 100644 (file)
 
 [
     GenerateIsReachable=ImplFrame,
-    NamedGetter,
     IndexedGetter,
     InterfaceName=PluginArray
 ] interface DOMPluginArray {
     readonly attribute unsigned long length;
     DOMPlugin item([Default=Undefined] optional unsigned long index);
-    DOMPlugin namedItem([Default=Undefined] optional DOMString name);
+    getter DOMPlugin namedItem([Default=Undefined] optional DOMString name);
     void refresh([Default=Undefined] optional boolean reload);
 };
 
index b23c1bd..bcbd3d7 100644 (file)
@@ -24,7 +24,6 @@
  */
 
 [
-    NamedGetter,
     GenerateIsReachable=ImplFrame,
     CustomDeleteProperty,
     CustomEnumerateProperty,
@@ -33,7 +32,7 @@
 ] interface Storage {
     [NotEnumerable, GetterRaisesException] readonly attribute unsigned long length;
     [NotEnumerable, TreatReturnedNullStringAs=Null, RaisesException] DOMString key(unsigned long index);
-    [NotEnumerable, TreatReturnedNullStringAs=Null, RaisesException] DOMString getItem(DOMString key);
+    [NotEnumerable, TreatReturnedNullStringAs=Null, RaisesException] getter DOMString getItem(DOMString key);
     [NotEnumerable, RaisesException] void setItem(DOMString key, DOMString data);
     [NotEnumerable, RaisesException] void removeItem(DOMString key);
     [NotEnumerable, RaisesException] void clear();