= Table of Contents = [#Overview Overview][[br]] [#Basics Basics of IDL][[br]] [#IDLAttributeChecker IDL attribute checker][[br]] [#RunBindingsTests run-bindings-tests][[br]] [#BindingsCode Where is the bindings code generated?][[br]] [#NamingRules Basic naming rules of IDL attributes][[br]] [#IDLAttributes IDL attributes] - [#TreatNullAs TreatNullAs(a,p), TreatUndefinedAs(a,p)][[br]] - [#TreatReturnedNullStringAs TreatReturnedNullStringAs(m,a)][[br]] - [#Default Default(p)][[br]] - [#Clamp Clamp(a,p)][[br]] - [#Custom Custom(m,a), CustomGetter(a), CustomSetter(a)][[br]] - [#CallWith CallWith(m,a)][[br]] - [#StrictTypeChecking StrictTypeChecking(m,a,p)][[br]] - [#ReturnNewObject ReturnNewObject(m,a)][[br]] - [#ImplementedAs ImplementedAs(m,a)][[br]] - [#Reflect Reflect(a)][[br]] - [#Replaceable Replaceable(a)][[br]] - [#Deletable Deletable(a), NotEnumerable(a)][[br]] - [#CachedAttribute CachedAttribute(a)][[br]] - [#JSWindowEventListener JSWindowEventListener(a)][[br]] - [#Constructor Constructor(i), ConstructorCallWith(i), ConstructorRaisesException(i)][[br]] - [#ConstructorTemplate ConstructorTemplate(i), InitializedByEventConstructor(a)][[br]] - [#NamedConstructor NamedConstructor(i)][[br]] - [#CustomConstructor CustomConstructor(i)][[br]] - [#Conditional Conditional(i,m,a)][[br]] - [#CheckSecurity CheckSecurity(i), DoNotCheckSecurity(m,a), DoNotCheckSecurityOnGetter(a), DoNotCheckSecurityOnSetter(a)][[br]] - [#CheckSecurityForNode CheckSecurityForNode(m,a)][[br]] - [#CustomIndexedSetter CustomIndexedSetter(i)][[br]] - [#CustomNamedGetter CustomNamedGetter(i), CustomNamedSetter(i)][[br]] - [#InterfaceName InterfaceName(i)][[br]] - [#EventTarget EventTarget(i)][[br]] - [#DoNotCheckConstants DoNotCheckConstants(i)][[br]] - [#ActiveDOMObject ActiveDOMObject(i)][[br]] - [#CustomEnumerateProperty CustomEnumerateProperty(i), CustomDeleteProperty(i)][[br]] - [#TypedArray TypedArray(i), ConstructorTemplate=TypedArray(i)][[br]] - [#CustomCall CustomCall(i)][[br]] - [#JSCustomToNativeObject JSCustomToNativeObject(i), JSCustomFinalize(i), CustomIsReachable(i), JSCustomMarkFunction(i), JSCustomNamedGetterOnPrototype(i), JSCustomPushEventHandlerScope(i), JSCustomDefineOwnProperty(i), JSCustomDefineOwnPropertyOnPrototype(i), JSCustomGetOwnPropertySlotAndDescriptor(i)][[br]] - [#JSGenerateToJSObject JSGenerateToJSObject(i), JSGenerateToNativeObject(i)][[br]] - [#GenerateIsReachable GenerateIsReachable(i)] - [#JSLegacyParent JSLegacyParent(i)][[br]] - [#JSInlineGetOwnPropertySlot JSInlineGetOwnPropertySlot(i)][[br]] - [#JSNoStaticTables JSNoStaticTables(i)][[br]] - [#ObjCProtocol ObjCProtocol(i), ObjCPolymorphic(i), ObjCLegacyUnnamedParameters(m), ObjCUseDefaultView(m), ObjCImplementedAsUnsignedLongLong(a)][[br]] - [#CPPPureInterface CPPPureInterface(i)][[br]] - [#CustomReturn CustomReturn(p)][[br]] - [#ArrayClass ArrayClass(i)][[br]] - [#Immutable Immutable, MasqueradesAsUndefined, CustomGetOwnPropertySlot, ReplaceableConstructor, IsIndex][[br]] - [#ImplementationNamespace ImplementationNamespace(i)][[br]] - [#SkipVTableValidation SkipVTableValidation(i), ImplementationLacksVTable(i),][[br]] - [#NoInterfaceObject NoInterfaceObject(i), GlobalContext(i)][[br]] - [#EnabledAtRuntime EnabledAtRuntime(i)][[br]] - [#RaisesException RaisesException(m) GetterRaisesException(a), SetterRaisesException(a)][[br]] = Overview = #Overview The [http://www.w3.org/TR/WebIDL/ Web IDL] is a language that defines how WebCore interfaces are bound to external languages such as JavaScriptCore, ObjC, GObject and CPP. You need to write IDL files (e.g. XMLHttpRequest.idl, Element.idl, etc) to expose WebCore interfaces to those external languages. When WebKit is built, the IDL files are parsed, and the code to bind WebCore implementations and JavaScriptCore, ObjC, GObject and CPP interfaces is automatically generated. This document describes practical information about how the IDL bindings work and how you can write IDL files in WebKit. The syntax of IDL files is fairly well documented in the [http://www.w3.org/TR/WebIDL/ Web IDL spec], but it is too formal to read:-) and there are several differences between the Web IDL spec and the WebKit IDL due to implementation issues. = Basics of IDL = #Basics Here is an example of IDL files: {{{ module core { [ CustomToJSObject ] interface Node { const unsigned short ELEMENT_NODE = 1; attribute Node parentNode; [TreatReturnedNullStringAs=Null] attribute DOMString nodeName; [Custom] Node appendChild([CustomReturn] Node newChild); void addEventListener(DOMString type, EventListener listener, optional boolean useCapture); }; } }}} Let us introduce some terminologies: * The above IDL file describes the Node '''interface'''. * ELEMENT_NODE is a '''constant''' of the Node interface. * parentNode and nodeName are '''attribute'''s of the Node interface. * appendChild(...) and addEventListener(...) are '''method'''s of the Node interface. * type, listener and useCapture are '''parameter'''s of the Node interface. * `[CustomToJSObject]`, `[TreatReturnedNullStringAs=Null]`, `[Custom]` and `[CustomReturn]` are '''IDL attribute'''s. Note: These terminologies are not aligned with the Web IDL spec. In the Web IDL spec, a 'method' is called an 'operation'. There is no distinction between an 'attribute' and a 'parameter' (a 'parameter' is treated as an 'attribute'). The key points are as follows: * An IDL file controls how the bindings code between JavaScript engine (or ObjC, GObject, CPP) and the WebKit implementation is generated. * IDL attributes enable you to control the bindings code more in detail. * There are 90~ IDL attributes and their roles are explained in the subsequent sections. * IDL attributes can be specified on interfaces, methods, attributes and parameters. Where each IDL attribute can be specified on is defined per each IDL attribute. This is also explained in the subsequent sections. A template of an IDL file is as follows: {{{ module MODULE_NAME { [ IDL_ATTRIBUTE_ON_INTERFACE1, IDL_ATTRIBUTE_ON_INTERFACE2, ... ] interface INTERFACE_NAME { const unsigned long value = 12345; [IDL_ATTRIBUTE_ON_ATTRIBUTE1, IDL_ATTRIBUTE_ON_ATTRIBUTE2, ...] attribute Node node; [IDL_ATTRIBUTE_ON_METHOD1, IDL_ATTRIBUTE_ON_METHOD2, ...] void func([IDL_ATTRIBUTE_ON_PARAMETER1, IDL_ATTRIBUTE_ON_PARAMETER2, ...] int param, ...); }; } }}} If there is no IDL attributes on interfaces, the IDL file just looks like this: {{{ module MODULE_NAME { interface INTERFACE_NAME { const unsigned long value = 12345; [IDL_ATTRIBUTE_ON_ATTRIBUTE1, IDL_ATTRIBUTE_ON_ATTRIBUTE2, ...] attribute Node node; [IDL_ATTRIBUTE_ON_METHOD1, IDL_ATTRIBUTE_ON_METHOD2, ...] void func([IDL_ATTRIBUTE_ON_PARAMETER1, IDL_ATTRIBUTE_ON_PARAMETER2, ...] int param, ...); }; } }}} = IDL attribute checker = #IDLAttributeChecker Previously there had been many bugs caused by typos of IDL attributes in IDL files. To avoid such bugs, the IDL attribute checker is introduced to the WebKit build flow to check if all the IDL attributes used in IDL files are implemented in code generators. If you use an IDL attribute not implemented in code generators, the IDL attribute checker fails, and the WebKit build fails. A list of IDL attributes implemented in code generators is described in WebCore/bindings/scripts/IDLAttributes.txt. If you want to add a new IDL attribute, you need to 1. add the IDL attribute to WebCore/bindings/scripts/IDLAttributes.txt. 1. add the explanation to this document. 1. add test cases to run-bindings-tests (explained below). = run-bindings-tests = #RunBindingsTests Tools/Scripts/run-bindings-tests tests IDL attributes. Specifically, run-bindings-tests reads WebCore/bindings/scripts/test/*.idl, and then generates bindings code to WebCore/bindings/scripts/test/{JS,ObjC,GObject,CPP}/*. For example, run-bindings-tests reads WebCore/bindings/scripts/test/TestObj.idl, and then generates bindings code to WebCore/bindings/scripts/test/JS/JSTestObj.h, WebCore/bindings/scripts/test/JS/JSTestObj.cpp, etc. If you change the behavior of code generators or add a new IDL attribute, please add test cases to WebCore/bindings/scripts/test/*.idl. You can reset the run-bindings-tests results using the --reset-results option: {{{ $ ./Tools/Scripts/run-bindings-tests --reset-results }}} The objective of run-bindings-tests is to show you and reviewers how the code generation is changed by your patch. '''If you change the behavior of code generators, please update the results of run-bindings-tests'''. That being said, run-bindings-tests is just for showing the change to you and reviewers, and the test failure is not critical for the WebKit build. People have been likely to forget to update the run-bindings-tests results in fact. Therefore, build bots do not treat the test failure as a failure. In this way, the run-bindings-tests results in the WebKit repository are sometimes wrong. If you find it, please rebaseline the run-bindings-tests before making your patch. If you make your patch without rebaselining the test results, the run-bindings-tests results will include the changes that had been caused by previous patches, which would be unreadable for you and reviewers. Anyway, ideally all people should update the run-bindings-tests results if their patch changes the behavior of code generators. = Where is the bindings code generated? = #BindingsCode By reading this document you can learn how IDL attributes work. However, the best practice to understand IDL attributes is to try to use some IDL attributes and watch what kind of bindings code is generated. If you touch any IDL file, all IDL files are rebuilt. The code generation is done at the very early step of the ./webkit-build command, so you can obtain the generated code in 1 minute. In case of XXX.idl in the Release build, the bindings code is generated in the following files ("Release" becomes "Debug" in the Debug build). * JavaScriptCore: {{{ WebKitBuild/Release/DerivedSources/WebCore/JSXXX.h WebKitBuild/Release/DerivedSources/WebCore/JSXXX.cpp }}} * ObjC: {{{ WebKitBuild/Release/DerivedSources/WebCore/DOMXXX.h WebKitBuild/Release/DerivedSources/WebCore/DOMXXX.mm }}} * GObject: {{{ WebKitBuild/Release/DerivedSources/webkit/WebKitDOMXXX.h WebKitBuild/Release/DerivedSources/webkit/WebKitDOMXXX.cpp }}} * CPP: {{{ WebKitBuild/Release/DerivedSources/WebCore/WebDOMXXX.h WebKitBuild/Release/DerivedSources/WebCore/WebDOMXXX.cpp }}} = Basic naming rules of IDL attributes = #NamingRules There are a few rules in naming IDL attributes: * A name should be aligned with the Web IDL spec as much as possible. * JavaScriptCore-specific IDL attributes are prefixed by "JS". * ObjC-specific IDL attributes are prefixed by "ObjC". * GObject-specific IDL attributes are prefixed by "GObject". * CPP-specific IDL attributes are prefixed by "CPP". * IDL attributes for custom bindings are prefixed by "Custom". For example, `[JSNoStaticTables]`, `[CustomGetter]`, etc. = IDL attributes = #IDLAttributes In the following explanations, (i), (m), (a) or (p) means that a given IDL attribute can be specified on interfaces, methods, attributes and parameters, respectively. For example, (a,p) means that the IDL attribute can be specified on attributes and parameters. == `[TreatNullAs]`(a,p), `[TreatUndefinedAs]`(a,p) == #TreatNullAs * [http://dev.w3.org/2006/webapi/WebIDL/#TreatNullAs The spec of TreatNullAs] (Note: The WebKit behavior explained below is different from the spec) * [http://dev.w3.org/2006/webapi/WebIDL/#TreatUndefinedAs The spec of TreatUndefinedAs] (Note: The WebKit behavior explained below is different from the spec) Summary: They control the behavior when a JavaScript null or undefined is passed to a DOMString attribute or parameter. Usage: The possible usage is `[TreatNullAs=NullString]` or `[TreatUndefinedAs=NullString]`. They can be specified on DOMString attributes or DOMString parameters only: {{{ [TreatNullAs=NullString] attribute DOMString str; void func([TreatNullAs=NullString, TreatUndefinedAs=NullString] DOMString str); }}} `[TreatNullAs=NullString]` indicates that if a JavaScript null is passed to the attribute or parameter, then it is converted to a WebKit null string, for which both String::IsEmpty() and String::IsNull() will return true. Without `[TreatNullAs=NullString]`, a JavaScript null is converted to a WebKit string "null". `[TreatNullAs=NullString]` in WebKit corresponds to `[TreatNullAs=EmptyString]` in the Web IDL spec. Unless the spec specifies `[TreatNullAs=EmptyString]`, you should not specify `[TreatNullAs=NullString]` in WebKit. `[TreatUndefinedAs=NullString]` indicates that if a JavaScript undefined is passed to the attribute or parameter, then it is converted to a WebKit null string, for which both String::IsEmpty() and String::IsNull() will return true. Without `[TreatUndefinedAs=NullString]`, a JavaScript undefined is converted to a WebKit string "undefined". `[TreatUndefinedAs=NullString]` in WebKit corresponds to `[TreatUndefinedAs=EmptyString]` in the Web IDL spec. Unless the spec specifies `[TreatUndefinedAs=EmptyString]`, you should not specify `[TreatUndefinedAs=NullString]` in WebKit. Note: For now the sole usage of `[TreatUndefinedAs=NullString]` is not allowed. `[TreatUndefinedAs=NullString]` must be used with `[TreatNullAs=NullString]`, i.e. `[TreatNullAs=NullString, TreatUndefinedAs=NullString]`. == `[TreatReturnedNullStringAs]`(m,a) == #TreatReturnedNullStringAs Summary: `[TreatReturnedNullStringAs]` controls the behavior when a WebKit null string is returned from the WebCore implementation. Usage: The possible usage is `[TreatReturnedNullStringAs=Null]`, `[TreatReturnedNullStringAs=Undefined]` or `[TreatReturnedNullStringAs=False]`. They can be specified on DOMString attributes or methods that return a DOMString value: {{{ [TreatReturnedNullStringAs=Null] attribute DOMString str; [TreatReturnedNullStringAs=Undefined] DOMString func(); }}} * `[TreatReturnedNullStringAs=Null]` indicates that if the returned DOMString is a WebKit null string, the returned value is treated as a JavaScript null. * `[TreatReturnedNullStringAs=Undefined]` indicates that if the returned DOMString is a WebKit null string, the returned value is treated as a JavaScript undefined. * `[TreatReturnedNullStringAs=False]` indicates that if the returned DOMString is a WebKit null string, the returned value is treated as a JavaScript false. Without `[TreatReturnedNullStringAs=...]`, if the returned DOMString is a WebKit null string, then the returned value is treated as a JavaScript empty string ''. Note that what should be specified on `[TreatReturnedNullStringAs=...]` depends on the spec of each attribute or method. == `[Default]`(p) == #Default Summary: `[Default]` allows specifying the default values for optional parameters to simplify WebCore implementations which otherwise require overloads. Standard: In Web IDL, `[Default=NullString]` is written as `"type identifier = default"`, e.g. `optional DOMString? str = null` Usage: The possible usages are `[Default=Undefined]` or `[Default=NullString]`. `[Default=Undefined]` can be specified on any optional parameter. `[Default=NullString]` can be specified on DOMString parameters only: {{{ interface HTMLFoo { void func1(int a, int b, optional int c, optional int d); void func2(int a, int b, [Default=Undefined] optional int c); void func3(int a, int b, [Default=Undefined] optional DOMString c, [Default=NullString] optional DOMString d); }; }}} The parameters marked with the standard Web IDL optional qualifier are optional, and JavaScript can omit the parameters. Obviously, if parameter X is marked with optional then all subsequent parameters of X should be marked with optional. The difference between optional and `[Default=Undefined]` optional is whether the WebCore implementation has overloaded methods or not, as explained below. In case of `func1(...)`, if JavaScript calls `func1(100, 200)`, then `HTMLFoo::func1(int a, int b)` is called in WebCore. If JavaScript calls `func1(100, 200, 300)`, then `HTMLFoo::func1(int a, int b, int c)` is called in WebCore. If JavaScript calls `func1(100, 200, 300, 400)`, then `HTMLFoo::func1(int a, int b, int c, int d)` is called in WebCore. In other words, if the WebCore implementation has overloaded methods, you can use optional. In case of `func2(...)` which adds `[Default=Undefined]`, if JavaScript calls `func2(100, 200)`, then it behaves as if JavaScript called `func2(100, 200, undefined)`. Consequently, `HTMLFoo::func2(int a, int b, int c)` is called in WebCore. 100 is passed to a, 200 is passed to b, and 0 is passed to c. (A JavaScript undefined is converted to 0, following the value conversion rule in the Web IDL spec.) In this way, WebCore needs to just implement `func2(int a, int b, int c)` and needs not to implement both `func2(int a, int b)` and `func2(int a, int b, int c)`. The difference between `[Default=Undefined]` and `[Default=NullString]` appears only when the parameter type is DOMString. In `[Default=Undefined]` the "supplemented" JavaScript undefined is converted to a WebKit string "undefined". On the other hand, in `[Default=NullString]` the "supplemented" JavaScript undefined is converted to a WebKit null string. For example, if JavaScript calls `func3(100, 200)`, then `HTMLFoo::func3(int a, int b, String c, String d)` is called in WebCore. At this point, 100 is passed to a, 200 is passed to b, a WebKit string "undefined" is passed to c, and a WebKit null string is passed to d. d.IsEmpty() and d.IsNull() return true. == `[Clamp]`(a,p) == #Clamp * [http://www.w3.org/TR/2012/CR-WebIDL-20120419/#Clamp The spec of Clamp] Summary: `[Clamp]` indicates that when an ECMAScript Number is converted to the IDL type, out of range values will be clamped to the range of valid values, rather than using the operators that use a modulo operation (ToInt32, ToUint32, etc.). Usage: The `[Clamp]` extended attribute MUST NOT appear on a read only attribute, or an attribute, operation argument or dictionary member that is not of an integer type. [Clamp] can be specified on writable attributes: {{{ interface XXX { [Clamp] attribute unsigned short attributeName; }; }}} [Clamp] can be specified on extended attributes on methods arguments: {{{ interface GraphicsContext { void setColor(octet red, octet green, octet blue); void setColorClamped([Clamp] octet red, [Clamp] octet green, [Clamp] octet blue); }; }}} Calling the non-`[Clamp]` version of `setColor()` uses ToUint8 to coerce the Numbers to octets. Hence calling `context.setColor(-1, 255, 257)` is equivalent to calling `setColor(255, 255, 1)`. Calling the `[Clamp]` version of `setColor()` uses `clampTo()` to coerce the Numbers to octets. Hence calling `context.setColor(-1, 255, 257)` is equivalent to calling `setColorClamped(0, 255, 255)`. == `[Custom]`(m,a), `[CustomGetter]`(a), `[CustomSetter]`(a) == #Custom Summary: They allow you to write bindings code manually as you like. Usage: `[Custom]` can be specified on methods or attributes. `[CustomGetter]`, `[CustomSetter]` can be specified on attributes: {{{ [Custom] void func(); [CustomGetter, JSCustomSetter] attribute DOMString str; }}} We should minimize the number of custom bindings as much as possible, since they are likely to be buggy. Before using `[Custom]`, you should doubly consider if you really need custom bindings. You are recommended to modify code generators to avoid using `[Custom]`. Before explaining the details, let us clarify the relationship of these IDL attributes. * `[Custom]` on a method indicates that you can write JavaScriptCore custom bindings for the method. * `[CustomGetter]` or `[CustomSetter]` on an attribute indicates that you can write JavaScriptCore custom bindings for the attribute getter or setter. You can write custom bindings with JavaScriptCore for a method or an attribute getter/setter, as follows: * Method: Consider the following example: {{{ interface XXX { [Custom] void func(int a, int b); }; }}} You can write custom bindings in WebCore/bindings/js/JSXXXCustom.cpp: {{{ JSValue JSXXX::func(ExecState* exec) { ...; } }}} Refer to WebCore/bindings/js/JSXXXCustom.cpp for more details. * Attribute getter: Consider the following example: {{{ interface XXX { [CustomGetter] attribute DOMString str; }; }}} You can write custom bindings in WebCore/bindings/js/JSXXXCustom.cpp: {{{ JSValue JSXXX::str(ExecState* exec) const { ...; } }}} Refer to WebCore/bindings/js/JSXXXCustom.cpp for more details. * Attribute setter: Consider the following example: {{{ interface XXX { [CustomSetter] attribute DOMString str; }; }}} You can write custom bindings in WebCore/bindings/js/JSXXXCustom.cpp: {{{ void JSXXX::setStr(ExecState*, JSValue value) { ...; } }}} Note: ObjC, GObject and CPP bindings do not support custom bindings. == `[CallWith]`(m,a) == #CallWith Summary: `[CallWith]` indicates that the bindings code calls a WebCore method with additional information. Usage: The possible usage is `[CallWith=X1|X2|X3|...]`, where X1, X2, X3, ... is "ScriptExecutionContext", "ScriptState", "ScriptArguments" or "CallStack". "ScriptExecutionContext", "ScriptState" and "CallStack" can be specified on methods or attributes, but "ScriptArguments" can be specified on methods only: {{{ interface HTMLFoo { [CallWith=ScriptExecutionContext] attribute DOMString str; [CallWith=ScriptExecutionContext] void func1(int a, int b); [CallWith=ScriptState] void func2(int a, int b); [CallWith=ScriptArguments|CallStack] void func3(int a, int b); [CallWith=CallStack|ScriptArguments] void func4(int a, int b); }; }}} Note: See `[ConstructorCallWith]` in the [#Constructor [Constructor] section] for similar functionality on constructors. In case of func1(...), HTMLFoo::func1(ScriptExecutionContext* context, int a, int b) is called in WebCore. Thus, in HTMLFoo::func1(...) you can retrieve document or window from context. In case of func2(...), HTMLFoo::func2(ScriptState* state, int a, int b) is called in WebCore. In case of func3(...), HTMLFoo::func3(ScriptArguments* arguments, ScriptCallStack* callstack, int a, int b) is called in WebCore. In this way, the additional information is added at the head of normal arguments. The order of additional information is "ScriptExecutionContext", "ScriptState", "ScriptArguments", and then "CallStack", despite the order specified in `[CallWith=X1|X2|X3|...]`. For example, in case of `func4(...)`, `HTMLFoo::func3(ScriptArguments* arguments, ScriptCallStack* callstack, int a, int b)` is called in WebCore. == `[StrictTypeChecking]`(m,a,p) FIXME == #StrictTypeChecking Summary: ADD SUMMARY Usage: `[StrictTypeChecking]` can be specified on methods and attributes: {{{ [StringTypeChecking] attribute float x; [StrictTypeChecking] DOMString func(); }}} ADD EXPLANATIONS JSC: `[StrictTypeChecking]` can also be applied to a DOMString parameter in an overloaded method to make the overload resolution only match for ECMAScript types null, undefined, string or object - and not number or boolean. This is to permit overloads which are not "distinguishable" in WebIDL, for example: {{{ interface CanvasFoo { void setColor([StrictTypeChecking] DOMString color); void setColor(float grayLevel); }; }}} == `[ReturnNewObject]`(m,a) == #ReturnNewObject Summary: `[ReturnNewObject]` controls whether WebCore can return a cached wrapped object or WebCore needs to return a newly created wrapped object every time. Usage: `[ReturnNewObject]` can be specified on methods or attributes: {{{ [ReturnNewObject] attribute Node node; [ReturnNewObject] Node createTextNode(); }}} Without `[ReturnNewObject]`, JavaScriptCore cache a wrapped object for performance. For example, consider the case where `node.firstChild` is accessed: 1. `Node::firstChild()` is called in WebCore. 1. The result of `Node::firstChild()` is passed to `toJS()`. 1. `toJS()` checks if a wrapped object of the result is already cached on the node. 1. If cached, the cached wrapped object is returned. That's it. 1. Otherwise, `toJS()` creates the wrapped object of the result. 1. The created wrapped object is cached on the node. 1. The wrapped object is returned. On the other hand, if you do not want to cache the wrapped object and want to create the wrapped object every time, you can specify `[ReturnNewObject]`. == `[ImplementedAs]`(m,a) == #ImplementedAs Summary: `[ImplementedAs]` specifies a method name in WebCore, if the method name in an IDL file and the method name in WebCore are different. Usage: The possible usage is `[ImplementedAs=XXX]`, where `XXX` is a method name in WebCore. `[ImplementedAs]` can be specified on methods: {{{ [ImplementedAs=deleteFunction] void delete(); [ImplementedAs=classAttribute] attribute int class; }}} Basically a method name in WebCore should be the same as the method name in an IDL file. That being said, sometimes you cannot use the same method name; e.g. "delete" is reserved for a C++ keyword. In such cases, you can explicitly specify the method name in WebCore by `[ImplementedAs]`. You should avoid using `[ImplementedAs]` as much as possible though. == `[Reflect]`(a) == #Reflect * [http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#reflect The spec of Reflect] Summary: `[Reflect]` indicates that a given attribute should reflect the values of a corresponding content attribute. Usage: The possible usage is `[Reflect]` or `[Reflect=X]`, where `X` is the name of a corresponding content attribute. `[Reflect]` can be specified on attributes: {{{ interface Element { [Reflect] attribute DOMString id; [Reflect=class] attribute DOMString className; }; }}} (Informally speaking,) a content attribute means an attribute on an HTML tag: {{{
}}} Here 'id' and 'class' are content attributes. If a given attribute in an IDL file is marked as `[Reflect]`, it indicates that the attribute getter returns the value of the corresponding content attribute and that the attribute setter sets the value of the corresponding content attribute. In the above example, 'div.id' returns 'foo', and 'div.id = "bar"' sets "bar" to the 'id' content attribute. If the name of the corresponding content attribute is different from the attribute name in an IDL file, you can specify the content attribute name by `[Reflect=X]`. For example, in case of `[Reflect=class]`, if `'div.className="barClass"'` is evaluated, then "barClass" is set to the 'class' content attribute. Whether `[Reflect]` should be specified or not depends on the spec of each attribute. == `[Replaceable]`(a) == #Replaceable * [http://dev.w3.org/2006/webapi/WebIDL/#Replaceable The spec of Replaceable] Summary: `[Replaceable]` controls if a given attribute is "replaceable" or not. Usage: `[Replaceable]` can be specified on attributes: {{{ interface DOMWindow { [Replaceable] attribute screenX; }; }}} Intuitively, "replaceable" means that you can set a new value to the attribute without overwriting the original value. If you delete the new value, then the original value still remains. Specifically, without `[Replaceable]`, the attribute behaves as follows: {{{ window.screenX; // Evaluates to 0 window.screenX = "foo"; window.screenX; // Evaluates to "foo" delete window.screenX; window.screenX; // Evaluates to undefined. 0 is lost. }}} With `[Replaceable]`, the attribute behaves as follows: {{{ window.screenX; // Evaluates to 0 window.screenX = "foo"; window.screenX; // Evaluates to "foo" delete window.screenX; window.screenX; // Evaluates to 0. 0 remains. }}} Whether `[Replaceable]` should be specified or not depends on the spec of each attribute. == `[Deletable]`(a), `[NotEnumerable]`(a)`(a) == #Deletable * [http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf The spec of Writable, Enumerable and Configurable (Section 8.6.1)] Summary: They control `Writability`, `Enumerability` attributes (`readonly` keyword controls the `Configurability` attributes). Usage: They can be specified on attributes: {{{ [NotEnumerable, Deletable] attribute DOMString str; readonly attribute DOMString readonlyStr; }}} By default, non-"readonly" attributes are enumerable, writable and not deletable. "readonly" attributes are enumerable, not writable and not deletable. You can change the default behavior using `[Deletable]`, `[NotEnumerable]` or `readonly`. * `[Deletable]` indicates that the attribute is deletable. * `[NotEnumerable]` indicates that the attribute is not enumerable. * `readonly` indicates that the attribute is read only. == `[CachedAttribute]`(a) == #CachedAttribute Summary: For performance optimization, `[CachedAttribute]` indicates that a wrapped object should be cached on a DOM object. Usage: `[CachedAttribute]` can be specified on attributes: {{{ interface HTMLFoo { [CachedAttribute] attribute DOMString normalValue; [CachedAttribute] attribute SerializedScriptValue serializedValue; }; }}} Without `[CachedAttribute]`, the normalValue getter works in the following way: 1. `HTMLFoo::normalValue()` is called in WebCore. 1. The result of `HTMLFoo::normalValue()` is passed to `toJS()`, and is converted to a wrapped object. 1. The wrapped object is returned. In case where `HTMLFoo::normalValue()` or the operation to wrap the result is weight, you can cache the wrapped object onto the DOM object. With `[CachedAttribute]`, the normalValue getter works in the following way: 1. If the wrapped object is cached, the cached wrapped object is returned. That's it. 1. Otherwise, `HTMLFoo::normalValue()` is called in WebCore. 1. The result of `HTMLFoo::normalValue()` is passed to `toJS()`, and is converted to a wrapped object. 1. The wrapped object is cached. 1. The wrapped object is returned. In particular, `[CachedAttribute]` will be useful for serialized values, since deserialization can be weight. Without `[CachedAttribute]`, the serializedValue getter works in the following way: 1. `HTMLFoo::serializedValue()` is called in WebCore. 1. The result of `HTMLFoo::serializedValue()` is deserialized. 1. The deserialized result is passed to `toJS()`, and is converted to a wrapped object. 1. The wrapped object is returned. In case where `HTMLFoo::serializedValue()`, the deserialization or the operation to wrap the result is weight, you can cache the wrapped object onto the DOM object. With `[CachedAttribute]`, the serializedValue getter works in the following way: 1. If the wrapped object is cached, the cached wrapped object is returned. That's it. 1. Otherwise, `HTMLFoo::serializedValue()` is called in WebCore. 1. The result of `HTMLFoo::serializedValue()` is deserialized. 1. The deserialized result is passed to `toJS()`, and is converted to a wrapped object. 1. The wrapped object is cached. 1. The wrapped object is returned. Note that you should cache attributes if and only if it is really important for performance. Not only does caching increase the DOM object size, but also it increases the overhead of "cache-miss"ed getters. In addition, setters always need to invalidate the cache. == `[JSWindowEventListener]`(a) FIXME == #JSWindowEventListener Summary: ADD SUMMARY Usage: `[JSWindowEventListener]` can be specified on `EventListener` attributes only: {{{ [JSWindowEventListener] attribute EventListener onload; }}} ADD EXPLANATIONS == `[Constructor]`(i), `[ConstructorCallWith]`(i), `[ConstructorRaisesException](i)` == #Constructor * [http://dev.w3.org/2006/webapi/WebIDL/#Constructor The spec of Constructor] Summary: `[Constructor]` indicates that the interface should have constructor, i.e. "new XXX()". `[ConstructorCallWith]` and `[ConstructorRaisesException]` add information when the constructor callback is called in WebCore. Usage: `[Constructor]`, `[ConstructorCallWith]` and `[ConstructorRaisesException]` can be specified on interfaces: {{{ [ Constructor(float x, float y, DOMString str), ConstructorRaisesException, ConstructorCallWith=ScriptExecutionContext ] interface XXX { }; }}} `[Constructor(float x, float y, DOMString str)]` means that the interface has a constructor and the constructor signature is `(float x, float y, DOMString str)`. Specifically, JavaScript can create a DOM object of XXX by the following code: {{{ var x = new XXX(1.0, 2.0, "hello"); }}} Then `XXX::create(float x, float y, String str)` is called in WebCore. That way WebCore needs to implement the following method as a constructor callback: {{{ PassRefPtr