I'm experimenting with ways to pre-compile a large number of JS functions using node.js vm.script, so that I can call the functions multiple times without the overhead of recompiling each time. Note that I can't just include the functions in a module, because they are architecturally completely separate from the "core" code. That works fine--each compiled script is stored in an object and can be run as-needed.
What I'm trying to figure out is how to use this same model with multiple fork'ed child processes, so any child process can be used to run the compiled script. The question is how to serialize it, so I can pass it to the child. And more importantly, is there anything inherent in the script variable that would "tie" it to the process it was created in?
I'm afraid is not possible. The first hint is that the Script object doesn't have any method to retrieve the compiled code. Looking further inside the source code of node here and here, it seems that the compiled object is stored inside a native C object. Therefore there's no means to serialize it from JS.
Related
There are a number of options for traversing a directory tree in Javascript (node-dir, fs.readdir, ...) and most supports asynchronous execution with a callback when finished.
But is there a framework that supports callbacks on each found file? I want to build a loader for audio files that incrementally adds the files as they are found.
Plain Javascript (or Typescript) solutions are also accepted.
I was thinking that traversing the structure was costly, and wanted to do the work for each file as it was found by the traversal, instead of collecting a list first. But experiments show that this is not the case, traversal is in fact very cheap compared to just opening a file, let alone parsing content. So I'll go with the suggestion from #Joseph and just use one of the options listed and call the function for each file.
I'll make this incremental by doing this asynchronously and update the UI reactively.
Thanks, for straightening out my thinking.
Quote from Defining JavaScript Resources In QML:
Some JavaScript files act more like libraries - they provide a set of helper functions that take input and compute output, but never manipulate QML component instances directly.
What if I want a JS file that both:
manipulates QML component instances (that are passed to it as arguments)
doesn't get a copy of its code and data stored for every QML component instance that imports it?
I could get the "no data stored on every instance" part by, well, not putting global variables in the JS file. But, for some strange reason, a copy of the "code" part seems to be stored for every instance as well. I don't get why this is but I want to know whether I can circumvent it, and at what cost.
I think that the line you quoted from the documentation is incorrect, or at least very poorly worded; you can still have a JS file with .pragma library in it and manipulate QML objects that are passed in as arguments to its functions. The sentence was probably referring to the previous section.
To share data across qml files, consider using a qml Singleton.
For data sharing purpose, I would not suggest using .pragma library (#Mitch) for following reasons.
.pragma library js provides limited functionality in qml object manipulation. While simple qml object manipulation (like property reading/writing) could be done with a .pragma library js, it does NOT allow creating/deleting qml objects (as you can in regular non-library js). It will suck when your application becomes dynamic.
.pragma library creating only one instance is merely an optimization in Qt implementation. It's never guaranteed that Qt creates exactly one instance, nor that your data would actually be shared.
Well, .pragma library is not designed to do data sharing work from the very beginning. Just, don't try to do it this way.
I am working on an application that utilizes Spider Monkey to run our JS. I only have a single object type (JSNode) that acts as an interface to a complex DOM consisting of various objects with properties and methods. Everything is created and registered on the fly. I am running into a problem where I have an object with a function that needs to be associated dynamically. The problem is when I run the script from the context of the associated object, the NewResolve (which I usually use to recognize and define the properties), as far as I can tell cannot know it's a function definition to allow me to define the function on the fly. I don't get the sense that JS_CompileScript will correctly build the function and associate it with the HandleObject. And of course I can't utilize JS_CompileFunction without doing all of the script parsing myself, which to me feels like the point of utilizing spider monkey in the first place, but maybe I am wrong.
Any ideas or guidance on this issue?
In my project I indirectly use some big arrays of data - in my specific case these are Minecraft block and item info.
As I said I'm using the data indirectly - one of my dependencies uses it. But now I want to use it too which means I'll need to require() that .js file that contains all the data. Since there are no constants in javascript and the loaded object will be mutable my question is if it will really be loaded two times in Node's memory. If it is, what can I do to save memory?
https://nodejs.org/docs/latest/api/modules.html#modules_caching
Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will get exactly the same object returned, if it would resolve to the same file.
So if your dependency is inside your project, and it requires the same file that you want to require - it will return the same object. But if your dependency A is a node module that requires dependency B (the big array) as a separate node module... And you add B as a dependency for your whole project, it will resolve to a different file. That means it will be a different object.
Modules are cached based on their resolved filename. Since modules may resolve to a different filename based on the location of the calling module (loading from node_modules folders), it is not a guarantee that require('foo') will always return the exact same object, if it would resolve to different files.
When you require the same file twice it only gets loading into memory once, you just get two references to it. The data will usually be mutable as well, so if one place modifies it the other place will see that change (which can lead to some confusing bugs!). You can avoid that either by using immutable data structures (like those in immutable.js) or by using Object.freeze (but be aware that this just does shallow immutability, so if any of the keys of your object are themselves mutable objects they will remain so).
I'm writing an Android app which uses Javascript in a WebView for most of the UI. I've exposed to JS a simple interface to create temporary files. In Java, I provide a function to create a temporary file, which returns a file ID, and a set of functions to operate on temporary files given an ID. In JS, I wrap these functions with a TempFile object which keeps track of its own ID internally.
The problem with this is the Java side has a list of files, but knows nothing about the objects that represent them in Javascript. So when a TempFile is collected in JS, the file object is still around on the Java side. Is there an "oncollect" or such callback that I can use to tell Java to free the file corresponding to a TempFile that's been collected?
Look at Finalizer
Since ES12 you can find FinalizationRegistry. Use it to tell Java to free the file corresponding to a TempFile that's been collected.
const registry = new FinalizationRegistry((fileName) => {
console.log(fileName);
// ... here your function to comunicate with Java
});
let tempFileObject;
registry.register(tempFileObject, filename);
Here we create an instance of FinalizationRegistry and attached the js 'tempFile' to it using .register. Soon as the 'tempFile' is garbage collected, the callback function passed to the FinalizationRegistry method communicate with java.
Possible duplicate
How to implement function that fires when JavaScript object is garbage collected?
I'm fairly sure the answer is "no" - you can't hook into the JS garbage collection process in the same way that you can with Java's finalizers (or ReferenceQueues).
Can you instead deal with this more declaratively? Your question seems to imply that the only way your system "knows" when a file is no longer needed, is when it is GCed (or in other words, your system doesn't know at all). Are you really referencing these files all over the application? Good practice would be for these resources to be used with a well-defined lifecycle, such that the part of the system that creates a temp file is also responsible for destroying it after it's finished with it.
Under that model, when you (explicitly) destroy the file in JS, you can call back to Java to perform the required clean up.
Releasing a resource by simply removing all references to it, as you're doing at the moment, is not particularly good practice.
No. You will need to call a Java function from your JavaScript when you don't need the files anymore.
Javascript does not have such hook.
You need to explicitly create close() function or such method for this use case and call it.
Some more info
http://forums.mozillazine.org/viewtopic.php?f=19&p=5517055