Prevent function name to get mangled while minification - javascript

I'm using gulp-uglify ~1.5.4 for my javascript minification, in a file a have this code : columns[j].colDef.cellRenderer.name === 'dateRenderer', cellRenderer is a function so cellRenderer.name will return he name of that function.
So when the function is dateRenderer() that code should return true which doesn't happens since after the minification the function got mangled.
I found this thread : Make gulp-uglify not mangle only one variable but I don't want to tell uglify what variables to mangle and not, isn't there any other way to solve this ? like in AngularJS we are using the $inject service.

If you don't want to specify to uglifyjs what function names should it skip from mangling, store that function's name as a string.
function dateRenderer() {
// do something useful
}
dateRenderer.rendererName = 'dateRenderer'
// later ...
var fn = dateRenderer
if (fn.rendererName === 'dateRenderer') {
console.log('ok!')
}
...or set its name after you called that specific function:
function dateRenderer() {
dateRenderer.rendererName = 'dateRenderer'
// do something useful
}
// later ...
var fn = dateRenderer
// do something
dateRenderer()
if (fn.rendererName === 'dateRenderer') {
console.log('ok!')
}

Related

Is it possible to identify a role after building a Vuejs project?

I have a file that exports some functions in a Vuejs project, and I need to use them also in an external environment .. inComponent I know which function I should use by identifying by name and comparing with a .JSON file this works cool in the environment of development but when I build the project the functions are renamed as in the image:
Is there any other reference in these functions where I can identify them other than by name? any reference in memory I don't know? Thank you!
You can define a unique value in the body of each function and then when you have a reference to one of the functions in your list you can call the toString() method of the function reference to get the source code of the function - and then check whether the desired unique value is present in the code.
Something like this:
const myFunc1 = function (...)
{
const uniqueIdent = 'zvjbesvfexrxe3cg4g3ewumkaj2hrz9m';
.....
}
const myFunc2 = function (...)
{
const uniqueIdent = 'y4wxfjedrr3mh6k5ju2gcff6wxafjcz5';
.....
}
// make the list of functions globally available
window.myFuncList = { myFunc1, myFunc2 };
// try to find the uglyfied name of Func2
var key;
var realNameFunc2;
for (key in window.myFuncList)
{
if (window.myFuncList[key].toString().indexOf('y4wxfjedrr3mh6k5ju2gcff6wxafjcz5') !== -1)
{
realNameFunc2 = key;
break;
}
}
// you can now invoke your function as realNameFunc2(...)

webpack plugin to replace a function with another

I am trying to create a webpack plugin, that will parse the code for a certain function and replace it with another function, that plugin will also expose the new function as a global.
class someName {
constructor(local, domain, translationFile, options) {
}
apply(compiler) {
// exposing ngt function as a global
compiler.plugin('make', function(compilation, callback) {
var childCompiler = compilation.createChildCompiler('someNameExpose');
childCompiler.apply(new webpack.DefinePlugin({
ngt: function(singular , plural, quantity) {
return quantity == 1 ? singular : plural;
}
}));
childCompiler.runAsChild(callback);
});
// searching for the getValue function
compiler.parser.plugin(`call getValue`, function someNameHandler(expr) {
// create a function to replace getValue with
let results = 'ngt('+ expr.arguments +')';
const dep = new ConstDependency(results, expr.range);
dep.loc = expr.loc;
this.state.current.addDependency(dep);
return true;
});
}
}
module.exports = someName;
update / rephrase
I have an issue here, when compiler.parser.plugin('call getValue', function someNameHandler(expr) {...} block is commented the ngt function exist as a global.
when its not commented, i get an error, ngt is undefined.
commented i mean /**/
I found a workaround for that but its far then idea. right now what I do is I export an anonymous function that does what i want.
You can see the plugin here:
Github
You can override the method based on environment. Let's say you have a method
function a(){
//original defination
}
Now based on the environment, if it's a production you could do something like this
if (environment.production) {
function a(){
//overridden defination
}
}
You can use the webpack-merge plugin, it's very useful to do exactly what do you want.
https://github.com/survivejs/webpack-merge

How can you recover the source code from a pure JavaScript function?

By Pure, I mean in the sense of the λ-calculus, i.e., a single-argument function containing nothing on its body other than single-argument functions and single argument function calls. By recovering the source code, I mean up to variable renaming. So, for example,
n2 = function(v0){return function(v1){return v0(v0(v1))}}
console.log(source(n2));
console.log(source(n2(n2)));
Should print:
function(v0){return function(v0){return v0(v0(v1))}}
function(v0){return function(v0){return v0(v0(v0(v0(v1))))}}
That is, the first line shows the original source of the function n2, and the second one shows the source of the function that is returned by the evaluation of n2(n2).
I've managed to implement it as follows:
function source(f){
var nextVarId = 0;
return (function recur(f){
if (typeof f === "function"){
if (f.isVarFunc) return f(null);
else {
var varName = "v"+(nextVarId++);
var varFunc = function rec(res){
var varFunc = function(arg){
return arg === null
? "("+res.join(")(")+")"
: rec(res.concat(recur(arg)));
};
varFunc.isVarFunc = true;
return varFunc;
};
varFunc.isVarFunc = true;
var body = f(varFunc([varName]));
body = body.isVarFunc ? body(null) : recur(body);
return "(function("+varName+"){return "+body+"})";
};
} else return f;
})(f);
};
The issue is that I'm using some rather ugly method of tagging functions by setting their names to a specific value, and that it won't work in functions that are applied more than once (such as a(b)(b)). Is there any better principled way to solve this problem?
Edit: I managed to design a version that seems to be correct in all cases, but it is still an ugly unreadable unprincipled mess.
Finally, this is a considerably cleaned up version of the mess above.
// source :: PureFunction -> String
// Evaluates a pure JavaScript function to normal form and returns the
// source code of the resulting function as a string.
function source(fn){
var nextVarId = 0;
return (function normalize(fn){
// This is responsible for collecting the argument list of a bound
// variable. For example, in `function(x){return x(a)(b)(c)}`, it
// collects `a`, `b`, `c` as the arguments of `x`. For that, it
// creates a variadic argumented function that is applied to many
// arguments, collecting them in a closure, until it is applied to
// `null`. When it is, it returns the JS source string for the
// application of the collected argument list.
function application(argList){
var app = function(arg){
return arg === null
? "("+argList.join(")(")+")"
: application(argList.concat(normalize(arg)));
};
app.isApplication = true;
return app;
};
// If we try to normalize an application, we apply
// it to `null` to stop the argument-collecting.
if (fn.isApplication)
return fn(null);
// Otherwise, it is a JavaScript function. We need to create an
// application for its variable, and call the function on it.
// We then normalize the resulting body and return the JS
// source for the function.
else {
var varName = "v"+(nextVarId++);
var body = normalize(fn(application([varName])));
return "(function("+varName+"){return "+body+"})";
};
})(fn);
};
It is still not perfect but looks much better nether less. It works as expected:
console.log(source(function(a){return function(b){return a(b)}}))
Outputs:
(function(v0){return (function(v1){return (v0)((v1))})})
I wonder how inefficient that is, though.

Reason for passing function to self executing function

I got js code from a design company, but I do not understand the reason for passing a function to a self executing function.
Here is the outline of the code.
(function(core) {
if (typeof define === "function" && define.amd) {
define("abc", function() {
var abc;
abc = window.Abc || core(window, window.jQuery, window.document);
abc.load = function(res, req, onload, config) {
var base, i, load, resource, resources;
resources = res.split(",");
load = [];
base = (config.config && config.config.abc && config.config.abc.base ? config.config.abc.base : "").replace(/\/+$/g, "");
if (!base) {
throw new Error("Please define base path to Abc in the requirejs config.");
}
i = 0;
while (i < resources.length) {
resource = resources[i].replace(/\./g, "/");
load.push(base + "/components/" + resource);
i += 1;
}
req(load, function() {
onload(abc);
});
};
return abc;
});
}
if (!window.jQuery) {
throw new Error("Abc requires jQuery");
}
if (window && window.jQuery) {
core(window, window.jQuery, window.document);
}
})(function(global, $, doc) {
var _c = {};
...
return _c;
});
Is there benefit of writing code such way over something like below?
(function( core, $, undefined) {
...
} (window.core= window.core|| {}, jQuery )};
Is this some advanced technique?
Basically, ....kinda.
In Javascript, functions are treated as first-class objects. This means you can pass them around in variables and whatnot. The first part, (function(core) { ... }), creates an anonymous function, taking a single argument called core. The parentheses around the function basically just resolve to a function. The second part, (function(global, $, doc) { ... }), is creating another function, which is passed immediately into a call to the first function as the value of core.
Put this way, here's what's happening.
// Define the first function (the one that takes core)
var firstFunc = function (core) { /* ... */ };
// Define the second function (the one that takes global, $, and doc)
var secondFunc = function (global, $, doc) {
var _c = {};
/* ... */
return _c;
};
// Call the first, passing in the second.
firstFunc(secondFunc);
The above code and the code you posted accomplish the same thing. One purpose for writing something like this would be to sandbox the second function so that the first can specify its own local versions of variables global, $, and doc, which avoids conflicts with, say, active-running versions of jQuery (which typically declares its own globally-scoped $ variable).
EDIT: Now that the code in the first function has been filled in, we can say for sure that the reason for doing this is to resolve dependencies and ensure they are present before manually passing them into the second function. From the look of the code provided, it appears that this is enforcing the presence of abc (which I'm assuming is some dependency) via require.js, as well as ensuring that jQuery is present. In addition, it looks like the values in _c returned from the function are used as a part of that dependency enforcement process, though I can't tell exactly how by looking at it.

How do I verify if several attributes are in a JSON structure within JavaScript?

I am creating a module that takes in several complicated JSON files and would like some code to give the user feedback if certain elements are absent.
Below is the way I am doing it now, but I cannot help to think there must be a cleaner, less hacky way.
var _und = require("underscore");
//this function takes a list of required attributes and ensures they are present
var check_req_attr = function(config, req_attr, callback) {
var config_attr = Object.keys(config);
var absent_attr = _und.difference(req_attr, config_attr); //slightly hacky code that checks to ensure config has correct vars
if (absent_attr.length !== 0) {
throw Error("missing following attributes from config:" + absent_attr);
} else {
callback();
};
};
It just feels...dirty. If there is no real elegant way to do it, I would be open to critiques on my code. Thanks!
Parse the JSON to JS.
var data = JSON.parse(theJson);
Use something like:
function hasKey(obj, key) {
return typeof obj[key] !== 'undefined';
};
function hasKeys(obj, keys) {
for (var i = 1, len = keys.length; i < len; i++) {
if (!hasKey(obj, keys[i])) {
return false;
};
};
return true;
};
Now you can simply do:
if (hasKeys(data, ["firstKey", "secondKey", "thirdKey"]) {
console.log("valid");
};
This should be the way to do it, using every and has:
if (_und.every(req_attr, function(attr) {
return _und.has(config, attr);
}))
throw new Error();
In a native environment, you would just use the in operator:
req_attr.every(function(attr){ return attr in config; })
I think your solution is actually quite elegant! No need for an anonymous function, and the loop (which must happen at some point, obviously) neatly abstracted away with difference.
Two suggestions:
I'd give the function a synchronous signature. No callback argument. There can't be any reason to go async if you honor the function signature (i.e. basing your answer on config and req_attr only).
I'd change the function to return the missing properties (attributes is wrong term). You could also add a requireProperties function that uses this "check" function that would throw if a property was missing. This allows for different kind of uses.
Why don't you try with something like:
obj = JSON.parse(json);
and then check
if(obj.YourProperty == undefined){
//do something..
}
Hope i understood your question.. It should work with complicated JSON files too.. Good luck ;)
You could also use the in operator (requiredAttr in obj):
function objHasAllRequiredAttrs(obj, attrNames) {
return attrNames.reduce(function(memo, attrName) {
return memo && (attrName in obj);
}, true);
}
objHasAllRequiredAttrs({foo:1}, ['foo']); // => true
objHasAllRequiredAttrs({bar:1}, ['foo']); // => false

Categories