Skip to content

Commit aa3a8a4

Browse files
authored
WebIDL Binder: Add 'BindTo' extended attribute to pick the called function (#22779)
This attribute can be used to change the C++ function that will be called. It can be used expose functions that have multiple overloads with the same number of parameters. Example: // C++ class BindToTest { public: int test(const char*) { return 1; } int test(int) { return 2; } }; // WebIDL interface BindToTest { void BindToTest(); [BindTo="test"] long testString([Const] DOMString arg); [BindTo="test"] long testInt(long arg); };
1 parent 12cedf4 commit aa3a8a4

File tree

9 files changed

+80
-5
lines changed

9 files changed

+80
-5
lines changed

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

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,55 @@ When C++ code has a pointer to a ``Base`` instance and calls ``virtualFunc()``,
416416
- You *must* implement all the methods you mentioned in the IDL of the ``JSImplementation`` class (``ImplJS``) or compilation will fail with an error.
417417
- You will also need to provide an interface definition for the ``Base`` class in the IDL file.
418418

419+
Function overloads
420+
==================
421+
422+
C++ allows function overloads, where multiple member functions have the same name but different arguments. By default, the *WebIDL Binder* allows you to bind overloaded functions if they differ only in the number of arguments:
423+
424+
.. code-block:: cpp
425+
426+
// C++
427+
class OverloadTest {
428+
public:
429+
void test(int arg1, int arg2) { ... }
430+
void test(int arg) { ... }
431+
};
432+
433+
.. code-block:: idl
434+
435+
// WebIDL
436+
interface OverloadTest {
437+
void OverloadTest();
438+
void test(long arg1, long arg2);
439+
void test(long arg);
440+
};
441+
442+
If your overloaded functions differ in some other way (say, in the types) then you can use the ``[BindTo]`` attribute to tell the tool what function name to bind to (that is, to call):
443+
444+
.. code-block:: cpp
445+
446+
// C++
447+
class BindToTest {
448+
public:
449+
void test(const char* arg) { ... }
450+
void test(int arg) { ... }
451+
};
452+
453+
.. code-block:: idl
454+
455+
// WebIDL
456+
interface BindToTest {
457+
void BindToTest();
458+
[BindTo="test"] void testString([Const] DOMString arg);
459+
[BindTo="test"] void testInt(long arg);
460+
};
461+
462+
In this case the C++ function ``test(const char*)`` will be named ``testString`` in JavaScript and ``test(int)`` will be named ``testInt``.
463+
464+
.. note::
465+
466+
You can also use ``[BindTo]`` to just rename a function, e.g. if you want to rename ``MyFunctionName`` to ``myFunctionName``.
467+
419468
Pointers and comparisons
420469
=========================
421470

test/webidl/post.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ new TheModule.Inner().incInPlace(new TheModule.Inner());
147147
console.log('add: ' + new TheModule.Inner(1).add(new TheModule.Inner(2)).get_value());
148148
console.log('mul2: ' + new TheModule.Inner(10).mul2(5));
149149

150+
let bindTo = new TheModule.BindToTest();
151+
console.log('testString: ' + bindTo.testString('hello'));
152+
console.log('testInt: ' + bindTo.testInt(10));
153+
150154
console.log(TheModule.enum_value1);
151155
console.log(TheModule.enum_value2);
152156

test/webidl/test.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,3 +242,9 @@ class ArrayArgumentTest {
242242
private:
243243
const char* m_array;
244244
};
245+
246+
class BindToTest {
247+
public:
248+
int test(const char*) { return 1; }
249+
int test(int) { return 2; }
250+
};

test/webidl/test.idl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,9 @@ interface JSArrayArgumentTest {
212212
boolean byteArrayTest([Const] byte[] arg);
213213
boolean domStringTest([Const] DOMString arg);
214214
};
215+
216+
interface BindToTest {
217+
void BindToTest();
218+
[BindTo="test"] long testString([Const] DOMString arg);
219+
[BindTo="test"] long testInt(long arg);
220+
};

test/webidl/test_ALL.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ getAsArray: 24
7373
Inner::+= => 2
7474
add: 3
7575
mul2: 50
76+
testString: 1
77+
testInt: 2
7678
0
7779
1
7880
34,34

test/webidl/test_DEFAULT.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ getAsArray: 24
7373
Inner::+= => 2
7474
add: 3
7575
mul2: 50
76+
testString: 1
77+
testInt: 2
7678
0
7779
1
7880
34,34

test/webidl/test_FAST.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ getAsArray: 24
7373
Inner::+= => 2
7474
add: 3
7575
mul2: 50
76+
testString: 1
77+
testInt: 2
7678
0
7779
1
7880
34,34

third_party/WebIDL.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3443,7 +3443,8 @@ def handleExtendedAttribute(self, attr):
34433443
identifier == "Value" or
34443444
identifier == "Operator" or
34453445
identifier == "Const" or
3446-
identifier == "WebGLHandlesContextLoss"):
3446+
identifier == "WebGLHandlesContextLoss" or
3447+
identifier == "BindTo"):
34473448
# Known attributes that we don't need to do anything with here
34483449
pass
34493450
else:

tools/webidl_binder.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,8 @@ def type_to_cdec(raw):
388388

389389
def render_function(class_name, func_name, sigs, return_type, non_pointer,
390390
copy, operator, constructor, is_static, func_scope,
391-
call_content=None, const=False, array_attribute=False):
391+
call_content=None, const=False, array_attribute=False,
392+
bind_to=None):
392393
legacy_mode = CHECKS not in ['ALL', 'FAST']
393394
all_checks = CHECKS == 'ALL'
394395

@@ -601,9 +602,10 @@ def make_call_args(i):
601602
elif call_content is not None:
602603
call = call_content
603604
else:
604-
call = func_name + '(' + call_args + ')'
605+
if not bind_to:
606+
bind_to = func_name
607+
call = bind_to + '(' + call_args + ')'
605608
if is_static:
606-
607609
call = c_class_name + '::' + call
608610
else:
609611
call = 'self->' + call
@@ -771,7 +773,8 @@ def add_bounds_check_impl():
771773
constructor,
772774
is_static=m.isStatic(),
773775
func_scope=m.parentScope.identifier.name,
774-
const=m.getExtendedAttribute('Const'))
776+
const=m.getExtendedAttribute('Const'),
777+
bind_to=(m.getExtendedAttribute('BindTo') or [None])[0])
775778
mid_js += ['\n']
776779
if constructor:
777780
mid_js += build_constructor(name)

0 commit comments

Comments
 (0)