Skip to content

Commit dcbb0b4

Browse files
ascorbickripken
authored andcommitted
webidl binder: define properties with JS accessors (#7298)
Currently C++ class and struct properties are defined in JavaScript bindings with get_foo and set_foo accessor methods. This PR adds support for directly accessing the properties using native JS accessors. For example: // Current way myObject.set_foo(1); console.log(myObject.get_foo()); // After this PR: myObject.foo = 1; console.log(myObject.foo); This is more idiomatic JavaScript, and means that the bindings match the IDL correctly. I have left the existing getters and setters in place, so this is be backward-compatible.
1 parent e21c600 commit dcbb0b4

File tree

10 files changed

+76
-7
lines changed

10 files changed

+76
-7
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,3 +364,4 @@ a license to everyone to use it as detailed in LICENSE.)
364364
* Zoltán Žarkov <[email protected]>
365365
* Roman Yurchak <[email protected]>
366366
* Hampton Maxwell <[email protected]>
367+
* Matt Kane <[email protected]>

site/source/docs/porting/connecting_cpp_and_javascript/WebIDL-Binder.rst

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,33 @@ If a C++ object does need to be cleaned up, you must explicitly call :js:func:`M
171171

172172
You will usually need to destroy the objects which you create, but this depends on the library being ported.
173173

174+
Attributes
175+
==========
176+
177+
Object attributes are defined in IDL using the ``attribute`` keyword. These can then be accessed in JavaScript using either ``get_foo()``/``set_foo()`` accessor methods, or directly as a property of the object.
178+
179+
.. code-block:: cpp
180+
181+
// C++
182+
int attr;
183+
184+
.. code-block:: idl
185+
186+
// WebIDL
187+
attribute long attr;
188+
189+
.. code-block:: javascript
190+
191+
// JavaScript
192+
var f = new Module.Foo();
193+
f.attr = 7;
194+
// Equivalent to:
195+
f.set_attr(7);
196+
197+
console.log(f.attr);
198+
console.log(f.get_attr());
199+
200+
For read-only attributes, see :ref:`webidl-binder-const`.
174201

175202
Pointers, References, Value types (Ref and Value)
176203
====================================================
@@ -215,7 +242,7 @@ If the C++ returns an object (rather than a reference or a pointer) then the ret
215242
// WebIDL
216243
[Value] MyClass process([Ref] MyClass input);
217244
218-
245+
.. _webidl-binder-const:
219246

220247
Const
221248
=====
@@ -246,7 +273,7 @@ Attributes that correspond to const data members must be specified with the ``re
246273
// WebIDL
247274
readonly attribute long numericalConstant;
248275
249-
This will generate a ``get_numericalConstant()`` method in the bindings, but not a corresponding setter.
276+
This will generate a ``get_numericalConstant()`` method in the bindings, but not a corresponding setter. The attribute will also be defined as read-only in JavaScript, meaning that trying to set it will have no effect on the value, and will throw an error in strict mode.
250277

251278
.. tip:: It is possible for a return type to have multiple specifiers. For example, an method that returns a contant reference would be marked up in the IDL using ``[Ref, Const]``.
252279

tests/webidl/output_ALL.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ Parent:42
44
object
55
object
66
8
7+
8
8+
8
9+
6
10+
6
11+
9
12+
10
13+
10
714
boolean
815
true
916
c1

tests/webidl/output_DEFAULT.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ Parent:42
44
object
55
object
66
8
7+
8
8+
8
9+
6
10+
6
11+
9
12+
10
13+
10
714
boolean
815
true
916
c1

tests/webidl/output_FAST.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ Parent:42
44
object
55
object
66
8
7+
8
8+
8
9+
6
10+
6
11+
9
12+
10
13+
10
714
boolean
815
true
916
c1

tests/webidl/post.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@ sme.parentFunc(90);
99
console.log(typeof sme.getAsConst());
1010
console.log(typeof sme.voidStar(sme));
1111
console.log(sme.get_immutableAttr());
12+
console.log(sme.immutableAttr);
13+
14+
try {
15+
sme.immutableAttr = 1;
16+
} catch(e) {}
17+
console.log(sme.immutableAttr); // Should be unchanged
18+
console.log(sme.attr);
19+
console.log(sme.get_attr());
20+
sme.attr = 9;
21+
console.log(sme.attr);
22+
sme.set_attr(10);
23+
console.log(sme.attr);
24+
console.log(sme.get_attr());
25+
1226
console.log(typeof sme.getBoolean());
1327
console.log(sme.getBoolean());
1428

tests/webidl/test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
#include "test.h"
77

8-
Parent::Parent(int val) : value(val), immutableAttr(8) { printf("Parent:%d\n", val); }
9-
Parent::Parent(Parent *p, Parent *q) : value(p->value + q->value), immutableAttr(8) { printf("Parent:%d\n", value); }
8+
Parent::Parent(int val) : value(val), immutableAttr(8), attr(6) { printf("Parent:%d\n", val); }
9+
Parent::Parent(Parent *p, Parent *q) : value(p->value + q->value), immutableAttr(8), attr(6) { printf("Parent:%d\n", value); }
1010
void Parent::mulVal(int mul) { value *= mul; }
1111

1212
typedef EnumClass::EnumWithinClass EnumClass_EnumWithinClass;

tests/webidl/test.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class Parent {
1515
const Parent *getAsConst() { return NULL; }
1616
void *voidStar(void *something) { return something; }
1717
bool getBoolean() { return true; }
18-
18+
int attr;
1919
const int immutableAttr;
2020
};
2121

tests/webidl/test.idl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ interface Parent {
99
[Const] Parent getAsConst();
1010
VoidPtr voidStar(VoidPtr something);
1111
boolean getBoolean();
12-
12+
attribute long attr;
1313
readonly attribute long immutableAttr;
1414
};
1515

tools/webidl_binder.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,10 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer, copy,
683683
const=m.getExtendedAttribute('Const'),
684684
array_attribute=m.type.isArray())
685685

686-
if not m.readonly:
686+
if m.readonly:
687+
mid_js += [r'''
688+
Object.defineProperty(%s.prototype, '%s', { get: %s.prototype.%s }) ''' % (name, attr, name, get_name)]
689+
else:
687690
set_name = 'set_' + attr
688691
mid_js += [r'''
689692
%s.prototype['%s'] = %s.prototype.%s = ''' % (name, set_name, name, set_name)]
@@ -697,6 +700,9 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer, copy,
697700
call_content=set_call_content,
698701
const=m.getExtendedAttribute('Const'),
699702
array_attribute=m.type.isArray())
703+
mid_js += [r'''
704+
Object.defineProperty(%s.prototype, '%s', { get: %s.prototype.%s, set: %s.prototype.%s }) ''' % (name, attr, name, get_name, name, set_name)]
705+
700706

701707
if not interface.getExtendedAttribute('NoDelete'):
702708
mid_js += [r'''

0 commit comments

Comments
 (0)