How to call a JavaScript function named `call` from dart - dart

Is there any way to call a JavaScript function named call() (in a nested object) from Dart or do I have to wait for Dart 2.0 from which the special handling of call() might get removed?
I have a JS Proxy like:
#JS()
class SomethingFancy {
external String call();
}
But as call() can be used to turn an object into a function, it makes it impossible to access the function of the JS object.
If I could, I would change the name of the method in Dart, but that's not supported by package:js:
/// By default the dart name is used. It is not valid to specify a custom
/// [name] for class instance members.
The error I get is:
Uncaught Error: NoSuchMethodError: method not found: 'call$0' (J.getSomethingFancy$1$x(...).call$0 is not a function)
If the function didn't exist, the error would look like this:
Uncaught Error: NoSuchMethodError: method not found: 'callMe' (receiver.callMe is not a function)
Other functions on the same object work just fine.

You can prefix call with JS$:
#JS()
class SomethingFancy {
external String JS$call();
}
JS$ can be used as prefix to allow to access to JS names that conflicts with dart keywords.

Related

How can I print the name of a generic type?

I have a dart method that takes a generic type.
At the top of the method I want to print the name of the type that was passed as T, is this possible?
eg
void myMethod<T> () {
print("myMethod called with type="+????);
}
If myMethod is called with myMethod() it would print "myMethod called with type=String".
Yes and no.
You can write
void myMethod<T> () {
print("myMethod called with type=$T");
}
The only problem is that the Dart libraries don't promise that a Type object (which is what T evaluates to) will have a toString which returns the source name of the type in the original program.
It generally does give that string, but if you compile for the web with "minification", it might not keep the source names available.
There is also no promise that the toString of Type won't change in the future, since it is entirely unspecified.

access html method that is not defined in dart2js

I need to access the replaceTrack method of the RtcRtpSender, however, it is not defined in the dart2js file:
#Native("RTCRtpSender")
class RtcRtpSender extends Interceptor {
// To suppress missing implicit constructor warnings.
factory RtcRtpSender._() {
throw new UnsupportedError("Not supported");
}
MediaStreamTrack? get track native;
}
The replaceTrack method is defined here: https://developer.mozilla.org/en-US/docs/Web/API/RTCRtpSender/replaceTrack
How can I call the RtcRtpSender.replaceTrack()?
I've tried the below and it threw _DartObject method not found:
JsObject.fromBrowserObject(myRtcRtpSender).callMethod('replaceTrack',
[null]);
thanks to #sunbreak in gitter he reminded me of dart:js_util:
import 'package:js/js_util.dart' as js_util;
js_util.callMethod(myRtcRtpSender, 'replaceTrack',
[null]);

Flutter: Using Intl.message without args and name parameters

When I run flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/localizations.dart, the generator skips over all Intl.message files that only include a string, printing:
Skipping invalid Intl.message invocation
<Intl.message("MESSAGE")>
reason: The 'args' argument for Intl.message must be specified for messages with parameters. Consider using rewrite_intl_messages.dart
from lib/main.dart line: 125, column: 9
The doc for the internationalization package says The name and args parameters must match the name (or ClassName_methodName) and arguments list of the function respectively. For messages without parameters, both of these can be omitted. But it seems to me that, in this case, my message is without parameters!
Am I misunderstanding what Dart devs mean by parameters?
Move it out of the constructor into a separate function. You can call the function from the constructor, but it has to be a single message alone in a function.
The reason is to support messages with parameters. The translation gets generated, at least conceptually, as a separate function. So we have
foo(String name) => Intl.message('Hello $name', name: 'foo', args: [name]);
in a deferred library fr_FR somewhere
foo(String name) => 'Bonjour $name'
and the implementation of Intl.message is conceptually
currentLanguage.lookup('foo').call(args)
So there can only be one message in a function because we're going to replace that function with something else. And it can't be a constructor because we can't just delegate to that.

Getting the parameters of a method call from a clang match callback

I'm adapting the Clang tool-template (as described here) to search for a particular method call in my code. In order to later rewrite that call, I would like to get the type of the parameters the method was called with, as well as the type of the object the method was called on.
I managed to find a matcher that calls back the following:
class AddListenerPrinter : public MatchFinder::MatchCallback
{
public :
virtual void run(const MatchFinder::MatchResult &Result) {
if (const auto *FS = Result.Nodes.getNodeAs<clang::MemberExpr>("ListeningBound"))
{
FS->dump();
}
}
};
which prints out:
MemberExpr 0x7fb05b07b948 '<bound member function type>' .addListener 0x7fb05b077670
`-MemberExpr 0x7fb05b07b918 'class MyCore' lvalue ->mCore 0x7fb05b078e30
`-CXXThisExpr 0x7fb05b07b900 'class MyComponent *' this
Now I can't find any way to retrieve the type of the object the method was called on (here class MyCore) or the type of the method argument (here class MyComponent).
How can I do this?
I found the answer by browsing the code of the existing matchers.
Using matcher = memberCallExpr( callee(methodDecl(hasName("addListener"))) )
I was able to retrieve a CXXMemberCallExpr node. Then getting the type of the object the method was called on:
// FS is the CXXMemberCallExpr
// Prints out the type of x in x.method()
llvm::outs() << FS->getRecordDecl()->getName();
and the method parameters are accessible through FS->getArg(n).
Bottom line is: Find the CXX object that contains what you're looking for first (e.g. which class has methods to access function arguments?), then find the matcher that will return the same type of object in ASTMatchers.h.
Hoping this can help anybody else with the same problem.

How to define a method for the class 'Proxy' in Dart js-interop?

I'm currently calling a jQuery based plugin called Bootstrap Context Menu.
In order to call it, I need to use the Javascript Interop library. But when I call a jQuery method from it I receive the following warning:
The method 'jQuery' is not defined for the class 'Proxy'
Code snippet:
js.scoped(() {
js.context.jQuery('#canvas').contextmenu();
});
This was not happening before some dart/js-interop updates. What is the right way to get rid of this warning?
You get this warning because the new analyzer doesn't seem to be aware of the option Report 'no such member' warnings when class defines noSuchMethod() ( Reported at http://dartbug.com/10016 ). If you switch back to the legacy analyzer you shouldn't see this warning anymore.
That said if you want to use the new analyzer and get rid of this warning you can use the array notation like this :
js.context["jQuery"]('#canvas')["contextmenu"]();
But :
it's less readable particullary for method calls.
it's less efficient for method calls because 2 operations are done ( f = js.context["jQuery"] followed by f('#canvas') ) instead of 1 ( js.context.jQuery('#canvas') )

Resources