Can Javascript file access objects from Python objects running? - javascript

let say in Javascript file
_myclass = new MyClass();
MyClass is not defined anywhere in the Javascript.
However, MyClass is a class defined by setup.py and that setup.py is running.
setup(name = 'MyClass',
version = '1.0',
author = '123',
when setup.py is not running then MyClass would be undefined in JAvascript.
Does this make any sense?

You can use the Django framework. To simplify what it does, let say you can write any python class and/or function and pass it to an html template. So basically it allows you to put your python variables in your JS script.
Hope it helps!

Related

Is it possible to only convert a dart function to javascript

I am currently using the following package where the readme illustrates the following
final bool loaded = await JsIsolatedWorker().importScripts(['test.js']);
I am using the isolate worker package so my code can work on web and outside of web. I would like to generate javascript code from my dart code. I have one file with a top level function and I use
dart compile js -O0 -o test.js test.dart
which I found here
https://dart.dev/tools/dart2js
this is my dart file
void main(List<String> args) {
doComputation('');
}
String doComputation(String input) {
return 'output';
}
I can generate javascript only if I have a main function but this generates a javascript file where the doComutation is not a top level function, so I am not sure if the package can call the function. It looks like it generates an entire program instead of just generating one function.
The generated file is too long to post
So what my question comes down to is this. Is there a way to generate javascript from dart for 1 function with its dependencies included instead of having to generate the entire program? So that I can call this function from dart.
I am not an expert but I also had this problem. Here's what worked for me:
In web_worker.dart:
import 'package:js/js.dart';
main(){
allowInterop(doComputation);
}
#JS('doComputation')
String doComputation(String computationInput) {
// Replace this with your actual computation.
final String computationOutput = "output";
return computationOutput;
}
Compile it using:
$ dart compile js web_worker.dart -o webWorker.js
Manually edit webWorker.js, the JS file generated by the compiler:
Delete this line at the top of the file:
(function dartProgram() {
and the line at the bottom of the file with the corresponding closing brace:
})();
I don't understand what's going on here but I found the Javascript version of the function doComputation() defined in webWorker.js as a property of the object "A".
I defined a wrapper at the top of the file like this:
function doComputation(computationInput) {
return A.doComputation(computationInput)
}
and then I was able to use the file with JsIsolatedWorker like this:
final bool loaded =
await JsIsolatedWorker().importScripts(['../web/webWorker.js']);
if (loaded) {
final String computationResult = await JsIsolatedWorker()
.run(functionName: 'doComputation', arguments: computationInput);
} else {
debugPrint('Web worker is not available');
}
If someone who understands this better can elaborate or improve on this solution, that would be great. I don't really have any idea what I'm doing. I'm just posting this to hopefully help other people save time in the future by sharing what worked for me.
You can use js package to call JavaScript APIs from Dart code, or vice versa. To make a Dart function callable from JavaScript by name, use a setter annotated with #JS().
#JS()
library callable_function;
import 'package:js/js.dart';
/// Allows assigning a function to be callable from `window.functionName()`
#JS('functionName')
external set _functionName(void Function() f);
/// Allows calling the assigned function from Dart as well.
#JS()
external void functionName();
void _someDartFunction() {
print('Hello from Dart!');
}
void main() {
_functionName = allowInterop(_someDartFunction);
}
JavaScript code may now call functionName() or window.functionName().
Check google chartjs https://github.com/google/chartjs.dart/tree/master/example for a complete example.
From dart2js "Helping dart2js generate better code" there is a tip :
Don’t worry about the size of your app’s included libraries. The dart2js compiler performs tree shaking to omit unused classes, functions, methods, and so on. Just import the libraries you need, and let dart2js get rid of what you don’t need.
Related to this post https://stackoverflow.com/a/21124252/3733730.
You can do this instead by using the package dart2js
one make a program for your main.dart dart2js where the function or command you wanted to make is there, then create a separate dart file what function you wanted to call, and it will fix your problem, it is a separate file but will only execute one function that you needed to do so and that is the separate file

PyMiniRacer adding Python classes to JS scope

Using PyMiniRacer, I would be able to use Python objects in Javascript; using the PyV8 library:
import PyV8
class Scope(PyV8.JsClass):
def __init__(self):
self.obj1 = Object1()
self.obj2 = Object2()
pythonScope = Scope()
context = PyV8.JsContext(pythonScope)
context.enter()
context.eval(...)
And using this code, the javascript can access the properties of Scope: obj1 and obj2
For PyMiniRacer, looking at the code, the MiniRacer class doesn't appear to accept any arguments into the constructor, so I don't see how I could add a Python Scope class into the JS scope. Is there a specific way of defining the class to be able to add a set of python classes to the JS scope, or do I need to inject them into the JS scope using a method I have missed while looking over the source code?
In the Ruby RubyRacer, (I understand that the RubyRacer and PyMiniRacer are individual projects by different authors, although PyMiniRacer is inspired by RubyRacer) objects in the Ruby scope can be embedded by calling context["funcName"] = funcName], but in Python...
>>> from py_mini_racer import py_mini_racer
>>> context = py_mini_racer.MiniRacer()
>>> def helloWorld(num):
return num * 2
>>> context["helloWorld"] = helloWorld
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
context["helloWorld"] = helloWorld
TypeError: 'MiniRacer' object does not support item assignment
>>>
...it raises an error. I also tried context.__dict__["helloWorld"] = "helloWorld", and running context.eval(helloWorld(5)) returns a ReferenceError: helloWorld is not defined error. All it does is allow me to call context.helloWorld(5) which doesn't help in executing from JS.
How can I insert Python objects into the JS scope such that in the JS code, I can call and access the methods and attributes from the Python object?
Unfortunately, PyMiniRacer does not support attaching Python objects or functions to a JavaScript Context so it is not possible to call Python code from the JavaScript code.

How can I extend a class in Node JS by my custom constructor?

I have the following in a Node Js model. This file exists in another project that cannot be changed but is locally available to the other projects.
module.exports = {
base: require('*/cartridge/models/product/decorators/base'),
availability: require('*/cartridge/models/product/decorators/availability')
};
All the methods here act like constructors of the class Product. Now I want to add another attribute that should be available when I try to access Product.badge. For this, I have tried to extend the above model in the following way:
var indexBase = require('*/cartridge/models/product/decorators/index');
indexBase.badge = require('*/cartridge/models/product/decorators/badge');
module.exports = indexBase;
But it seems throw an error, I have tried to log the Badge Type, but I still cannot access the badge type here.
I am calling the above object as the following:
var decorators = require('*/cartridge/models/product/decorators/index');
decorators.badge(product, variantProduct);
I want to know how can I extend an existing class as I want to add a custom constructor?
Here only the syntax is based on Node Js but this code is written for SFRA in Salesforce B2C Commerce.
All you need to do is in the index.js file:
var indexBase = module.superModule;
instead of:
var indexBase = require('*/cartridge/models/product/decorators/index');
and it will work perfectly fine.

Separate Typescript files in build config

I guess I have a rather complicated problem.
I use a JS environment in which JS script are executed separately, let's say JS is used as a script language like LUA in minecraft or other games an so on. These script may be called when a user clicks a button and they run on the server side of my application.
I compile my TS files to JS but the Typescript transpiler does not know that the TS files it compiles do exist (life) in the same environment. An example:
types.d.ts
interface Person {
name: string;
age: number;
}
interface Car {
maxv: number;
brand: string;
}
person.ts
var steven = new Person();
car.ts
var steven = new Car();
For my purpose this is valid code. person.js might be bound to a button a user clicks and car.js might be a job script on my server. These scripts are executed completely seperatly but Typescript doesn't know that. That's why I get an error that I may not set steven to a variable of a different type that before.
Is there a way to tell Typescript "Hey, These files are not existing together"?
I already thought about putting every script into a namespace ...
person.ts
module person {
export function run() {
var steven = new Person();
// further script code
}
}
... but I don't like that approach.

Reading JavaScript variables using Selenium WebDriver

I'm using Selenium WebDriver (Java) and TestNG to do some testing on a website I created. In this website, I also have JavaScript and in some of the functions, it returns values and also outputs values to the browser console through console.log().
I was wondering if there is an easy way for Selenium WebDriver to access some of this JavaScript information so I can perform assertions using TestNG.
I'm quite new to Selenium but I understand that you can do something like:
WebDriver driver = new ChromeDriver();
driver.findElement(By.id("btn")).click();
So is there anything similar I can do using WebDriver to read the JavaScript on the site?
Clarification
It looks like people are making the assumption that I'm trying to "execute" JavaScript code through Selenium.
Thats not the case. Instead, I'm trying to store already-defined JavaScript variable using Selenium.
Basically, I want Selenium to be able to grab the JavaScript variable's value, store it locally, and then do an assertion test on it.
Attempt 1
Say I have the following JS code for my website:
$(document).ready(function() {
var foo = $(#"input-field-val").val();
function returnFoo() {
return foo;
}
});
From what I've reading and understanding, in my seperate Selenium test file (Selenium.java), I should be able to do something like this?:
public class Selenium {
WebDriver driver = new FirefoxDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;
#Test
public void testSample() {
driver.get("www.mywebsite.com");
js.executeScript("alert(returnFoo());");
}
}
I do something similar to what's above but no alert box pops up. Instead, I get an error message:
Exception in thread "main" org.openqa.selenium.WebDriverException: ReferenceError: returnFoo is not defined
I'm pretty sure I'm not understanding what it means when its said that the JS variable
should not be part of a closure or local variable
I have also tried defining a global variable above the $(document).ready(function()... and setting is within function returnFoo() but still doesn't work.
Attempt 2
I've moved both foo and returnFoo() outside of the $(document).ready(function().... That has fixed ReferenceError message that I was getting in Attempt 1 above.
I hav also given foo a value so my JS code looks something like this:
var foo = "Selenium test run";
$(document).ready(function() {
...
});
function returnFoo() {
return foo;
}
Now, I'm having a tough time assigning the return of returnFoo() to a local variable within my Selenium test. Here's what I've attempted:
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;
driver.get("http://localhost:8080/HTML5TestApp/prod.html");
Object val = js.executeScript("window.returnFoo();");
System.out.println(val);
}
But the console display null instead of the actual value of "Selenium test run".
Attempt 2 - SOLUTION
It looks like if I do Object val = js.executeScript("alert(returnFoo());"); I get the value of foo.
SOLUTION
So here's the solution I've come up w/ to my problem thanks to the solution by Martin Foot below.
In my JavaScript file, I created a var and a setter/getter function like so:
index.js
var seleniumGlobal;
$(document).ready(function() {
...
)};
function setSG(toSet) {
seleniumGlobal = toSet;
}
function getSG() {
return seleniumGlobal;
}
SampleTest.java
// Do all the necessary imports
public class SampleTest {
WebDriver driver = new FirefoxDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;
#Test
public void testPrintVal() {
String sgVal = (String) js.executeScript("alert(getSG());");
Assert.assertEquals("new value for seleniumGlobal", sgVal);
}
}
So whenever some code in my JavaScript sets my seleniumGlobal variable through the setter method, I can call it through my Selenium test and do assertions on it.
This is probably not the most efficient way to do but if someone else has a better solution, please let me know.
All you have to do is:
Object val = js.executeScript("return returnFoo();");
That will give you what you are looking for.
No JavaScript functions need be defined. Nor is alert() needed.
Object result = js.executeScript("return globalVar");
For Python:
result = driver.execute_script("return globalVar")
In Ruby you can use page.execute_script to evaluate a JavaScript variable (if it is accessable from the scope of the web browser). It looks like there is a similar method in Java here.
Edit: This might be a use case that is more suited to a JavaScript unit testing framework such as Jasmine.

Categories

Resources