First, I transpose the javascript example into a dart one.
JS
Parse.Cloud.define('hello', function(request, response) {
response.success('Hello world');
});
DART
import 'dart:js' show allowInterop;
import 'package:js/js.dart' show JS;
#JS('Parse.Cloud.define')
external void define(String name, Function func);
void main() {
define('hello', allowInterop((req, res) {
res.success('Yeah!');
}));
}
Then I compile it using dart2js (with csp or not).
Finally I run parse deploy and I get
ReferenceError: self is not defined
at <error: TypeError: Object #<error> has no method '__lookupGetter__'>
at main.js:2539:9
at init.currentScript (main.js:2519:7)
at main.js:2534:5
at main.js:2542:3
and now, here I am...
How I could get it work on parse.com which is a nodejs env I presume.
self is effectively not defined in the environement provided by parse.com, so I defined self such as var self = this; in the dart2js output.
I get a new error, about success$1 is not defined. Well, that's true, my code is still incomplet...
Dart code should like this:
import 'dart:js' show allowInterop;
import 'package:js/js.dart' show JS, anonymous;
#JS('Parse.Cloud.define')
external void define(String name, Function func);
#JS()
#anonymous
class HttpResponse {
external void success(String msg);
external void error(String msg);
}
void main() {
define('hello', allowInterop((req, HttpResponse res) {
res.success('Yeah!');
}));
}
Now, everything work. I can enjoy my sunday.
Related
I have a NodeJS/TypeScript app that uses Selenium WebDriver, which has approximately this snippet:
import { WebDriver } from "selenium-webdriver";
export class MyClass {
public async getTimeOrigin(driver: WebDriver): Promise<number> {
return await driver.executeScript(function () {
// This should be the DOM's timeOrigin (same as if a person types "performance.timeOrigin"
// into the Chrome DevTools console)
return performance.timeOrigin;
});
}
}
When I attempt to build the above, I get the following error message:
error TS2339: Property 'timeOrigin' does not exist on type 'Performance'
But it does certainly exist, since I can looks up the references on the Performance object and see timeOrigin inside. Can anyone please advise on how to fix this and correctly access the timeOrigin property?
performance is a global variable which is only available to the web browser you test. While you're working in NodeJS environment, it doesn't have any global performance, that's why Typescript cannot detect it and throw the error when compiling.
To fix this, you only need a simple global variable declaration:
declare var performance: any;
If you're using a lot of web interfaces in your Node environment, I recommend you import the lib lib.dom to typescript to avoid these types of errors:
{
"compilerOptions": {
"lib": [
"dom"
]
}
}
As mentioned by mcernak, another way is to use string as input to executeScript function.
To avoid the compilation issues, you can provide the script that you want to execute in context of the browser as a string(instead of a function):
public async getTimeOrigin(driver: WebDriver): Promise<number> {
return await driver.executeScript("return performance.timeOrigin;");
}
From the documentation of WebDriver.executeScript:
Executes a snippet of JavaScript in the context of the currently
selected frame or window. The script fragment will be executed as the
body of an anonymous function. If the script is provided as a function
object, that function will be converted to a string for injection into
the target window.
Maybe you can try to cast it as Performance.
import { WebDriver } from "selenium-webdriver";
export class MyClass {
public async getTimeOrigin(driver: WebDriver): Promise<number> {
return await driver.executeScript(function () {
// This should be the DOM's timeOrigin (same as if a person types "performance.timeOrigin"
// into the Chrome DevTools console)
const perf = <Performance>performance; // or "performance as Performance"
return perf.timeOrigin;
});
}
}
I have lots of app.use(...) in my express app, and they get messy and complex and there's config all over the place. So I want to move them to separate modules so they're easier to test.
So I have this Middleware.ts base class for my middleware wrappers:
export default abstract class Middleware {
public run(): express.RequestHandler {
try {
return this.runImpl;
}
catch (err) {
log("Failed to init middleware " + err);
throw err;
}
}
public abstract runImpl(): express.RequestHandler;
}
And a subclass, e.g. StaticMiddleware.ts for serving static files:
export class StaticMiddleware extends Middleware {
public runImp(): express.RequestHandler {
// this is a simple example, but most middleware are more
// complicated, but everything is encapsulated here
return express.static("path");
}
}
export default new StaticMiddleware().run;
Finally the app.ts express app itself, which is very clean:
import staticMiddleware from "./StaticMiddleware";
import fooMiddleware from "./FooMiddleware";
import barMiddleware from "./BarMiddleware";
app.use(staticMiddleware());
app.use(fooMiddleware());
app.use(barMiddleware());
But I get an error at runtime:
TypeError: app.use() requires a middleware function
Note it's possible to change the method signatures above, so I can use this form:
app.use(staticMiddleware);
But that is surprising to a maintainer, and so liable to break. I want the normal signature:
app.use(staticMiddleware());
I am trying to use the trace method to print a string on the screen. I thought that Haxe code should work in Flambe, but apparently it doesn't. I tried to run this code but all I get is a black screen:
package urgame;
class Main {
static public function main():Void {
trace("Hello World");
}
}
I took the code from this haxe guide.
I also tried to use this code but the result is identical (black screen):
package urgame;
import flambe.Entity;
import flambe.System;
import flambe.asset.AssetPack;
import flambe.asset.Manifest;
import flambe.display.FillSprite;
import flambe.display.ImageSprite;
import flambe.display.Sprite;
class Main
{
private static function main ()
{
// Wind up all platform-specific stuff
System.init();
// Load up the compiled pack in the assets directory named "bootstrap"
var manifest = Manifest.fromAssets("bootstrap");
var loader = System.loadAssetPack(manifest);
loader.get(onSuccess);
}
private static function onSuccess (pack :AssetPack)
{
trace('Hello World');
}
If you run the html version the traces should be displayed in the browser console. So do build and run (debug build) and hit F12 in the browser.
As an experiment, I'm trying some stuff out with dart and easyrtc. I started at porting this (it is normally served through a nodejs server, found here) to a dart version and this is what I made from it
EDIT: I found out which part of the code is causing the error. It is the data object proxy which the for loop is unable to run through. Normally, the setRoomOccupantListener function gives as parameters the name of the room and an object with all the peers connected to the room. I have made a screenshot of the object layout in normal javascript as how it looks when I debug in chrome, found here.
function connect() {
easyrtc.setRoomOccupantListener(convertListToButtons);
}
function convertListToButtons (roomName, data, isPrimary) {
clearConnectList();
var otherClientDiv = document.getElementById("otherClients");
for(var easyrtcid in data) {
var button = document.createElement("button");
button.onclick = function(easyrtcid) {
return function() {
performCall(easyrtcid);
};
}(easyrtcid);
var label = document.createTextNode(easyrtc.idToName(easyrtcid));
button.appendChild(label);
otherClientDiv.appendChild(button);
}
}
And here is the screenshot when i debug the dart code in chromium
void connect() {
easyrtc.setRoomOccupantListener(convertListToButtons);
}
void convertListToButtons(roomName, data, isPrimary) {
clearConnectList();
var otherClientDiv = querySelector("#otherClients");
for (var easyrtcid in data) {
var button = document.createElement("button");
button.onClick.listen((event) {
performCall(easyrtcid);
});
button.appendText(easyrtc.idToName(easyrtcid));
otherClientDiv.append(button);
}
}
This is the error I get:
Class 'Proxy' has no instance getter 'iterator'.
NoSuchMethodError: method not found: 'iterator' Receiver: Instance of 'Proxy' Arguments: []
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:45)
#1 P...<omitted>...7)
Am I missing something simple here or is this some kind of incompatibility? Thank you.
I see you can use import package:js/js.dart'; too. I don't know how to use it
You could try
import 'dart:js' as js;
https://www.dartlang.org/articles/js-dart-interop/
This looks weird too
easyrtc = js.context.easyrtc; // <== here you have context 'easyrtc'
easyrtc.easyApp('easyrtc.audioVideo', 'selfVideo', new js.JsObject.jsify(['callerVideo']), loginSuccess, loginFailure);
// and here again 'easyrtc.audioVideo', I guess this is one to much
try
easyrtc.easyApp.callMethod('audioVideo', ['selfVideo', js.JsObject.jsify(['callerVideo']), loginSuccess, loginFailure]);
where 'audioVideo' is the called method and the rest are arguments
easyrtc.callMethod('easyApp', ['audioVideo', 'selfVideo', js.JsObject.jsify(['callerVideo']), loginSuccess, loginFailure]);
where 'easyApp' is the called method and the rest are arguments.
If you can add how the code would look in JavaScript I could create better examples.
Like dart:js package:js doesn't handle directly Dart List. So the following line :
easyrtc.easyApp('easyrtc.audioVideo', 'selfVideo',
['callerVideo'], loginSuccess, loginFailure);
should be :
easyrtc.easyApp('easyrtc.audioVideo', 'selfVideo',
js.array(['callerVideo']), loginSuccess, loginFailure);
See also What is a difference between dart:js and js package?
The coffee script code:
class ClassA
constructor: ->
alert ("Hello World")
Generating Javascript code use Web Essentials or Mindscape:
(function() {
var ClassA;
ClassA = (function() {
function ClassA() {
alert("Hello World");
}
return ClassA;
})();
}).call(this);
But when I use http://js2coffee.org/ or http://coffeescript.org/ will be Generating:
var ClassA;
ClassA = (function() {
function ClassA() {
alert("Hello World");
}
return ClassA;
})();
Why a different? How should I generating the second code in VS2012?
Thanks!
The difference between the two versions is simply given by using or not using the top-level function safety wrapper. http://coffeescript.org/#lexical-scope
The default is to use it, so you get the result you see in Visual Studio.
http://js2coffee.org/ and http://coffeescript.org/ use the --bare option.
see http://coffeescript.org/#usage