I have some simple JavaScript file named test.js the file contain the following code:
function foo(){
console.log('hi');
}
Since all client code is exposed to the client, I am trying to 'hide' it or to make it unreadable.
I downloaded uglify-js, I tried to run the command
uglifyjs test.js --output test.min.js
Then the output file contains the following:
function foo(){console.log("hi")}
i.e almost the same code, readable code
Am I missing something?
Your function foo is defined in the global scope, so its name can't be obfuscated/minified. Changing it might break other codes that were calling this function.
All other words are either keywords (function), built in objects (console), object methods (.log) or string literals ('hi'). These can't be changed without breaking your code.
So, all in all, there is no changes because nothing can be changed.
Related
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
I have been reading about AMD and implementations like requirejs. Most of the resources covers the usage and API's.
But, when it comes to implementing this, how can you load a JavaScript file into a variable just like that? For example, you can see functions like this:
define(['jquery'], function($){
});
var jquery = require('./jquery');
From an API consumer's perspective, all I can understand is that the file jquery.jshas magically become $, jQuery etc? How is that achieved?
Any examples would be helpful.
How do AMD loaders work under the hood? is a helpful read.
Edit: I think the eval answers below are nice because it actually is an eval problem in some ways. But I would like to know this from the perspective of an AMD specs implementation.
You don't load a javascript file into a variable, this is instead done by things such as browserify or webpack. Javascript itself can do this, but these modules generate a single file containing all your code. By calling require("file"), you are calling browserify's function to load a file named "file" stored in the code.
An example of this can be if you have a module
function demoModule(){
console.log("It works!");
}
module.exports = demoModule
This makes module.exports now contain the "entire" contents of the file
Browserify/webpack puts that into a function that returns the module.exports of that file
function require(filename) {
switch(filename){
case "demofile":
let module = {exports:{}}; ((module) => {
function demoModule(){
console.log("It works!");
}
module.exports = demoModule
})(module)
return module.exports;
}
};
require("demofile")();
Your file becomes a function that you can call with require("demofile") and it returns anything that was a module.export.
You know how you can say eval(alert("hello!")) and it executes the code?
You can also:
var str = "hello!"
eval('alert("' + str + '");')
So the next step is to have a file that has your actual script in it:
var str = "hello"
alert(str)
then you can use a standard AJAX request to fetch that file into a variable, and you can eval() that variable.
Technically, eval() is considered evil - fraught with dangers - but there are other solutions (for example, injecting a script tag into the document body). I just went with eval() here to make the explanation easier.
Extending what theGleep said.
Something like this:
var str = "if (x == 5) {console.log('z is 42'); z = 42;} else z = 0;";
console.log('z is ', eval(str));
For more read here.
But use eval() very cautiously and be absolutely sure about the pitfalls and drawbacks of eval().
Don't use it unless it is the only option.
Read this answer too.
The way define works under the hood is not by loading an "HTML Script into a variable". Typically a normal script can have multiple variables so it doesn't make sense to capture the value a variable! The eval approaches can probably do something like that if needed. It captures all that is there in the JavaScript source code.
The real key in AMD is that the define API maps a name to a function. Whenever you require with that name, it would just call that function and return the value to you. This return value is expected to be the module. This is a convention that makes everything work!
In other words, AMD uses an interesting convention (design pattern) to ensure that we get a modularization effect in JavaScript code. It is one level of indirection. Instead of the normal style of "write your code and get it executed in the global scope" paradigm, you just write a function that returns a single value that captures all the things you want to expose as a module to the consumer!
I have two JS files. One is called common.js and it use $.getScript to include other file with my js code. Part of including looks like this:
jQuery.getScript(js_path + "table.js", function(){
generateTable(chartData, dataTypes);
});
This file (common.js) also contains function compare(a, b).
Now, the second one (table.js) has declared different function which uses the compare function from the first file. Something like this:
function someName() {
var a = 2,
b = 5;
var test = compare(a, b);
return test;
}
When I run the code it gives me:
Uncaught ReferenceError: compare is not defined
How can I use function from the first file.
jQuery.getScript first fetches the JS file from the server, then executes it. If you want to work with global functions (as it seems) you need to pay attention to the following:
Your compare function must be declared before the table.js file is executed.
The compare function must be declared on the global namespace of table.js.
Sorry but without more info this is all you can get.
If your main file, as something like:
(function() {
function compare(){...}
}());
Then the compare function is not declared in the global namespace.
did you check the order of imports? The file with 'compare' method should be first. It should solve the problem.
What I would suggest is to skip getScript if it's just for separating the code.
<script src="common.js"></script>
<script src="table.js"></script>
<script src="app.js"></script>
Where common functions go into common, your table stuff goes into table. This way you get the ordering right. This also clears out the circular dependency one might see a hint of if table depends on common that depends on table by extracting all but the 'common' parts into some form of 'app'.
Is there a way to prevent emscripten from creating window scoped global "Module"?
I generate some .js using something like emcc --bind -O3 --memory-init-file 0 whatever.... If I include the output script, window object gets flooded with various internal emscripten functions and objects.
I tried to wrap generated code like this:
Some.Namespace.Whatever = (function() { ...generated code...; return Module;})();
Everything seems to work fine, but emscripten still creates window scoped global "Module" (other internal functions are gone).
Since this commit from February 4th this year, which I believe is part of Emscripten > v1.29.9, if the code is wrapped by some method, the Module object is not exposed on the global scope.
Maybe you can use the pre and post js options to wrap the code in a self executing anonymous function? [0] So he pre js would be (function () { and post js would be })();. This could just as easily be done manually as part of a build step with Unix cat.
That or shove it in a worker. [1]
I don't think emscripten assigns window.Module or this.Module in emitted code, but I'm not a computer to check right now, maybe you could?
[0] https://github.com/kripken/emscripten/blob/1c12291bcb77fac633d9fbe08c817746c4ce24c3/site/build/text/docs/tools_reference/emcc.txt#L269-L277
[1] https://github.com/kripken/emscripten/blob/1c12291bcb77fac633d9fbe08c817746c4ce24c3/site/build/text/docs/tools_reference/emcc.txt#L468-L474
I'm going to build a rather complicated application in html5 with some heavy javascripting.
In this I need to make some objects which can be pass around. But since there is no like #import foobar.js.
Then I assume that if my html page loads the scripts, then all the scripts can access eachother?
I read (here) that ajax somehow is able to load a .js file from within another .js file. But i dont think this is what I need?
Can go more into details if needed, thanks in advance.
In our projects, we do the following: Suppose you're going to call your project Foo, and have a module called Bar in it,
Then what we do is declare a file called Foo.js that just defines an equivalent to a Foo namespace:
Foo = (function(){
return {
};
})();
Then we create a file called Foo.Bar.js that contains the code for the Bar module:
Foo.Bar = (function(){
// var declarations here that should be invisible outside Foo.Bar
var p, q;
return {
fun1 : function(a, b){
// Code for fun1 here
},
fun2 : function(c) {
// Code for fun2 here
}
} // return
})();
Note that how it is a function that executes immediately, and returns an object that gets assigned to Foo.Bar. Any local variables, like p and q are available to fun1 and fun2 because they're in a closure, but they are invisible outside of Foo.Bar
The functions in Foo.Bar can be constructors for objects and so on.
Now in your HTML you simple include both files like so:
<script type="text/javascript" src="Foo.js"></script>
<script type="text/javascript" src="Foo.Bar.js"></script>
The result will be that you can call Foo.Bar's functions in the JavaScript of your main HTML file without any problems.
You should check out the module pattern:
http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth/
This describes alternatives for creating modular code in javascript, how you can protect your code and share APIs and data among them.
You should also consider using and AMD. Require.js is quite popular, but I tend to prefer head.js for this. Keep in mind that these put some requirements on how you structur your code in files, and personally, I don't think it's worth it, compared to a concatenated and minified file included in the bottom of the page.
Then I assume that if my html page loads the scripts, then all the scripts can access eachother?
Yes.