The C++11 specification defined [[attributes]] which can be used to specify/influence implementation-defined behavior. Cheerp supports this for specifying whether you're writing C++ code meant to be compiled into [[cheerp::genericjs]] or [[cheerp::wasm]] code. This results in your C++ code being compiled into the .js or .wasm output of the compiler respectively. (Right?)
My question: What attributes does Cheerp know and what do they all do?
So far, I've seen the following attributes:
[[cheerp::genericjs]]
[[cheerp::wasm]]
[[cheerp::asmjs]]
[[cheerp::client_layout]]
[[cheerp::static]]
[[cheerp::jsexport]]
The ones that are meant to be used by users are:
cheerp::genericjs: compile the associated item (class/struct definition, global, or function) to JavaScript, using the object memory model
cheerp::wasm: compile the associated item (class/struct definition, global, or function) to WebAssembli OR asm.js, using the linear memory model.
cheerp::asmjs is an alias of cheerp::wasm and considered obsoleted (but kept for backward compatibility). The actual output (wasm or asm.js) depends on command line flags
client::jsexport: export the associated item (function or class/struct) so that it can be used from external JavaScript code
The other attributes you mention do exist, but you should almost never use them yourself. Their meaning is this:
cheerp::static: tell the compiler that the associated method of a client class is static (example: Date.now()). Used in the implementation of various browser apis
cheerp::client_layout: tell the compiler that this class/struct has an external layout defined in external JavaScript. You never need to use this if you inherit your client classes from client::Object (which you should), because derived classes inherit this attribute
Related
I have a system (it happens to be Gatsby, but I don't believe that's relevant to this question) which is using webpack DefinePlugin to attach some EnvironmentVariables to the global variable: process.env
I can read this just fine.
Unfortunatley, due to weirdnesses in the app startup proces, I need have chosen to do some brief overwritting of those EnvironmentVariables after the site loads. (Not interested in discussing whether that's the best option, in the context of this question. I know there are other options; I want to know whether this is possible)
But it doesn't work :(
If I try to do it explicitly:
process.env.myVar = 'foo';
Then I get ReferenceError: invalid assignment left-hand side.
If I do it by indexer (which appears to be what dotenv does) then it doesn't error, but also doesn't work:
console.log(process.env.myVar);
process.env['myVar'] = 'foo';
console.log(process.env.myVar);
will log undefined twice.
What am I doing wrong, and how do I fix this?
The premise behind this attempted solution was flawed.
I was under the impression that webpack "made process.env.* available as an object in the browser".
It doesn't!
What it actually does is to transpile you code down into literals wherever you reference process.env. So what looks like fetch(process.env.MY_URL_VAR); isn't in fact referencing a variable, it's actually being transpiled down into fetch("http://theActualValue.com") at compile time.
That means that it's conceptually impossible to modify the values on the "process.env object", because there is not in fact an actual object, in the transpiled javascript.
This explains why the direct assignment gives a ref error (you tried to execute "someString" = "someOtherString";) but the indexer doesn't. (I assume that process.env gets compiled into some different literal, which technically supports an indexed setter)
The only solutions available would be to modify the webpack build process (not an option, though I will shortly raise a PR to make it possible :) ), use a different process for getting the Env.Vars into the frontEnd (sub-optimal for various other reasons) or to hack around with various bits of environment control that Gatsby provides to make it all kinda-sorta work (distasteful for yet other reasons).
Browsing the v8 tree, under the src directory, some js files were there, providing some basic JS objects like Math, Array etc. Browsing those files, I saw identifiers including a percent sign (%) in their names, i.e. %Foo. I first naively thought it was some other allowed character in JS's identifiers, but when I tried it in shell, it yelled at me, saying that I'm violating syntax rules. But if it is a syntax error, how come d8 works? Here are an example from the actual source code:
src/apinatives.js lines 44 to 47, git clone from github/v8/v8
function Instantiate(data, name) {
if (!%IsTemplate(data)) return data;
var tag = %GetTemplateField(data, kApiTagOffset);
switch (tag) {
src/apinatives.js lines 41 to 43, git clone from github/v8/v8
function SetConstructor() {
if (%_IsConstructCall()) {
%SetInitialize(this);
How come this identifiers do not yield syntax errors. All js files, including math.js and string.js and all others?:wq
It is not technically valid JavaScript. These are calls to V8 runtime functions. From that page:
Much of the JavaScript library is implemented in JavaScript code
itself, using a minimal set of C++ runtime functions callable from
JavaScript. Some of these are called using names that start with %,
and using the flag "--allow-natives-syntax". Others are only called by
code generated by the code generators, and are not visible in JS, even
using the % syntax.
If you look in parser.cc you can see some code relating to allow_natives_syntax that determines whether the parser will accept this extension to the JavaScript language that V8 is using to interact with its runtime. These files must be parsed with that option enabled.
I would speculate that V8 does not allow you to make these calls by default both because it would contradict the JavaScript standard and because it would probably allow you to do things to the runtime you should not be able to do.
As far as I know, Asm.js is just a strict specification of JavaScript, it uses the JavaScript features and it's not a new language.
For instance, instead of using var a = e;, it offers var a = e|0;.
My question is, if asm.js is just a definition and can be achieved by changing the way one uses and declares variables and dynamic types, what does "use asm"; actually do? Is this necessary to put this string before declaring function's body or not?
Asm.js is a very strict subset of JavaScript, that is optimized for machines rather than humans. If you want your browser to interpret certain code as asm.js code, you need to create a module wherein the following conditions apply :
all code is fully statically typed and limited to the very restrictive asm.js subset of JavaScript
your module starts with the "use asm" pragma
Additionally, an asm.js module allows only up to three optional yet very specific parameters :
a standard library object, providing access to a subset of the JavaScript standard libraries
a foreign function interface (FFI), providing access to custom external JavaScript functions
a heap buffer, providing a single ArrayBuffer to act as the asm.js heap
So, your module should basically look like this :
function MyAsmModule(stdlib, foreign, heap) {
"use asm";
// module body...
return {
export1: f1,
export2: f2,
// ...
};
}
The function parameters of your module allow asm.js to call into external JavaScript and to share its heap buffer with "normal" JavaScript. The exports object returned from the module allows external JavaScript to call into asm.js.
Leave out the "use asm", and your browser will not know that it should interpret your code as an asm.js module. It will treat your code as "ordinary" JavaScript. However, just using "use asm" is not enough for your code to be interpreted as asm.js. Fail to meet any of the other criteria mentioned hereabove, and your code will be also interpreted as "ordinary" JavaScript :
For more info on asm.js, see eg. John Resig's article from 2013 or the official specs.
"use asm" is a pragma that tells the JavaScript engine specifically how to interpret it. Although it's valid JavaScript and can be used without the pragma, FireFox can perform additional optimizations to the Asm.js subset to increase performance. To do this, it must know that it is Asm.js.
jade permits you to simply write
include folder/file
to include code from another file.
Is it possible to add simply cut - copy style code from another file in node for javascript files?
Its for development purpose, to isolate some code and work on it seperately.
PS:- I'm aware of require('jsfile.js') and export.x = function(){..
The accepted answer is wrong.
Depending on whether node fs and eval were available at the time this question was written, the accepted answer was probably always wrong.
While not recommended, what you want to do is essentially possible:
Use node's built-in filesystem functions to read the file you want to "copy-paste" into the current file.
Use eval() to "paste" that file into your current file and run it as if it was part of the current file.
https://github.com/dennishall/node-require-without-require
Update 6 Oct 2020: Embarrassingly, the answer I've provided below is false.
I am not certain what were the circumstances for my writings below, as I was familiar with eval at the time (and a very long time before then), however, it is what it is :)
Read the answer that #Dennis wrote for the correct one.
You cannot merge (or include) a script file into another script file during runtime. Utilizing require is your best option to separate your application logic into multiple files.
JavaScript is an object oriented language, and what you are asking for is a solution to a problem that exists in procedural programming languages.
I suggest that you design your application in such a way that would allow you to separate its files into object types that take on different responsibilities instead of treating each file as a script within some global state.
To answer your other question, Jade is actually parsing its source files and therefore can provide its own file merging. If we apply this to our scenario, Jade is to jade source files as V8 is to JavaScript source files. Since the jade language is procedural, it makes sense to allow this kind of feature where in JavaScript (which is object oriented) it doesn't.
My webapp is based on a common script where I define the common functions and a global variable and dynamically loaded scripts that process those. So far, the only way I found to export the global variable is to replace any occurrence by window["myGlobalVar"] but I find it very ugly. Is there a better way to do?
Here is an illustration
// commonscript.js before compilation
function incrementVariable() {window["myGlobalVar"]++;}
window["incrementVariable"] = incrementVariable;
window["myGlobalVar"] = 0;
and in another script
alert(myGlobalVar); // <= alerts 0
incrementVariable();
alert(myGlobalVar); // <= alerts 1
I am looking for a way to use directly myGlobalVar in both files because it would be more elegant. However, I would need to set window["myGlobalVar"] to a pointer and not a copy of the object and I am not sure how to do that on simple types.
Is it possible? Is encapsulating myGlobalVar in an Object the only other way?
Thanks a lot for your lights.
New Answer
Closure-compiler supports an #nocollapse annotation which prevents a property from being collapsed to a global variable. This allows the property to be mutable when exported.
#nocollapse does not block renaming - you still need to export a property to accomplish that.
#nocollapse is currently only supported when compiling from source. It will be included in the next release - that is versions AFTER the v20150315 release.
Old Answer
#expose is now deprecated. The compiler will warn about any usage of #expose
There is a new, but so far undocumented, annoatation: #expose. This single annotation will both export a property and prevent it from being collapsed off a constructor. It sounds like the perfect fit for your situation - but it will require your variable to be a property on an object.
However, use with care. Any properties which have #expose will not be renamed and will not be removed as dead code. This makes it especially problematic for use by javascript library writers.
If you want to have a variable that doesn't get renamed, just create a file called for example props.txt with the following contents:
myGlobalVar:myGlobalVar
Then when compiling your code, add the command line argument: --property_map_input_file props.txt
Your variable will not be renamed and is available to all scripts as long as it's not optimized away. Also, if you don't declare it at all (so you omit var myGlobalVar), it won't get renamed or removed.