PyMiniRacer adding Python classes to JS scope - javascript

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.

Related

Foreign variables display as 'undefined'

Hello to anyone who will read this post,
I have two standalone javascript files, one of which possesses a class with variables that I would like to use in the other file. We will call the file that possesses the class script.js, and the other file index.js. The code inside index (which is the main file we want to run) compiles fine, but when I run it, my variable prints out as 'undefined'. The variables work fine when they are inside index file themselves, but inside the script.js's class, they are undefined. I would very much like to keep script.js, and keep my variables inside the class. I use an object instance that we will call script obj, and I would very much like to keep my objects. I am not a fan of the static method.
Example: Script.js's class
class script{
constructor(){
var laggies = parseInt(1)
}
}
Above, laggies is defined with a value of 1. Nice, yes? Now let us look at index.js(Just pretend that the object has been initialized)
Example:
console.log(obj.laggies)
This is where I get my problem. I am using repl.it with node version 12.16.1
Thank you for your time.
You are getting the undefined error because the class does not have a variable called laggies. Its defined inside the constructor of the class and not elsewhere.
Try this
class script{
constructor() {
this.laggies = parseInt( 1)
}
}

Declaring dynamic prototype methods to typescript

I'm converting a javascript class with several "generated" prototype methods to typescript. The generated methods are mapped to an internal object so the API is cleaner/more convenient for 80% of its use cases.
However, I'm find no way to properly tell typescript which methods exist without actually implementing them.
class A {}
A.prototype.test = function() {}
var a = new A().test();
It errors with error TS2339: Property 'test' does not exist on type 'A'
It seems like I can get around it by defining the property manually, but that hinders the usefulness of automatically mapping these methods.
class A {
test: any;
}
A.prototype.test = function() {}
var a = new A();
a.test();
However, I'm find no way to properly tell typescript which methods exist without actually implementing them.
If the methods are generated why even define the class? i.e. instead of class A you really should only be declaring the class i.e. you should be doing:
declare class A {
test();
}
I can get around it by defining the property manually
Yes. Because of the dynamic part, the type cannot be statically inferred by TypeScript. It has to be manually defined:
class A {
test: () => void;
}
A.prototype.test = function() {}
Or, another way that I use sometimes:
Dynamically build the API in TypeScript module files, that export some members;
Compile to JavaScript code;
Write a file index.d.ts that declares the exported module members of the API (like the answer of #basarat);
In a separated project (with another tsconfig.json), import the module members of the API, from the JavaScript code, with the help of the declarations in index.d.ts.
This process is particularly suited to publish a npm package.

export function to global scope in scalajs

Question about scalajs and javascript.
How to mark a function to be purely exported to global scope?
Given scala object in top level package
#JSExport
object Foo{
def apply(a: Int, b: Int): String = "bar"+a+b
}
I would like to compile this scala code into javascript and have this function named Foo in global scope. In other words I would like to have a javascript similar to this:
function Foo(a,b) {
return 'bar'+a+b;
}
Is it possible using scalajs?
I am writing component in javascript, which will be referenced from third party API which can not be influenced by me. This is why I simply need to follow their rules and provide javascript functions in global scope.
The solution to this is now Top Level Exports, as documented under the now-closed issue #1381 - to use this feature, tag a function in an object with #JSExportTopLevel.
object A {
#JSExportTopLevel("foo")
def foo(x: Int): Int = x + 1
}
<Foo will be available from JavaScript's global namespace>
(See https://www.scala-js.org/doc/interoperability/export-to-javascript.html for the official documentation, under "Exporting top-level methods".)
You currently cannot do this without executing some code. But you can have setup code that assigns it:
import scala.scalajs.js
object App extends js.JSApp {
def main(): Unit = {
js.Dynamic.global.anything = // your js.FunctionN
}
}
There is an issue open (#1381) to have language support for this.

Can Javascript file access objects from Python objects running?

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!

Integration clojurescript into a javascript framework

I would like to use Clojurescript to write a component within a Javascript framework but I can't work out how to create the constructor and call global variables within the object.
The framework creates views (within their own .js file) by reading their state from a saved jason file and reifying them in javascript (the views are code like so):
(function() {
var Title = function(json) {
view.View.call(this, json); // view is defined in another js file - global namespace
this.title = json.title;
this.el.addClass("title");
}
view.inherit(view.View, Title);
view.Title = Title;
view.types.Title = Title;
Title.prototype.json = function() {
return $.extend(view.View.prototype.json.call(this), {
type: 'Title',
title: this.title
});
}
Title.prototype.reflow = function() {
this.h2.quickfit(opts);
}
})();
I have seen how you create a Javascript object using deftype macro and Object:
(deftype Foo [a b c]
Object
(bar x (+ a b c x)))
I'm new to both javascript and clojurescript. I see that the anonymous function wrapping everything provides a scope for the view but not sure how to (or if I need to) so something equivalent in clojurescript.
So my questions are:
how do I create the constructor function for Title in this model??
And do how should I handle the calls to the view variable, such as view.inherit etc?
Thanks
This is a bit general of an answer, but you seem to be wanting to share code between both ClojureScript and JavaScript, so here is a primer and a few select tidbits on Using JavaScript Libraries in Clojure:
Exporting
Protecting symbols you declare from renaming is easy; just define :export metadata on any ClojureScript var, and the ClojureScript compiler will ensure that it is not munged.
For example, a function can be declared like this:
(ns example)
(defn ^:export hello [name]
(js/alert (str "Hello," name "!")))
It is then available, via the same name, in an external JavaScript context:
<script>
example.hello("Eustace")
</script>
Externs
In order to go the other way, and reference a variable declared externally from within your code, you must provide the Google Closure compiler with an "extern file", a .js file defining javascript variables which will not be munged. This file is passed to the Google Closure compiler, and when compiling, it will not munge any names defined in it.
For example, I can try compiling the following ClojureScript (utilizing the Raphael.js library) in advanced mode without an extern file.
(defn test []
(let [raphael (js/Raphael. 10 50 320 200)]
(. raphael (circle 50 50 50))))
When I call the test function, it will throw a javascript error that new Raphael(10, 50, 320, 200)).K is not a function. K is the munged name of the circle function from Raphael, and obviously can't be found, since it isn't defined anywhere. We need to tell the compiler to preserve the name circle, not munge it.
I can do this by creating the following externs.js file:
var Raphael = {};
Raphael.circle = function() {};
And use it when compiling my ClojureScript:
(closure/build "src/cljs" {:optimizations :advanced
:externs ["externs.js"]
:output-to "helloworld.js"})

Categories

Resources