Javascript function .toString() in webpack - javascript

In my webpack developing case, I need to output function as strings by function.toString(). But webpack may translate some statements into module styles.
const myFunc = function{
this.methods.log(Date.now())
}
myFunc.toString()
"myFunc(){this.methods.log(_Users_xxx_Desktop_designer_web_node_modules_babel_runtime_corejs2_core_js_date_now__WEBPACK_IMPORTED_MODULE_3___default()());}"
What I need:
"myFunc(){this.methods.log(Date.now())}"
I handled this pointer to correct object. I just want webkit to ignore this function.

For this particular case the transformation is done first by babel, cus you use transform-runtime plugin, it decides that the Date API needs to come from core-js. Webpack steps in later because it sees Date now refer to a imported lib, so it transform the import statement to WEBPACK_IMPORT_MODULE.
You either tune babel to disallow it transform Date, or you can do the reverse. You write a string of function, then eval it to get a real function.
const myFuncStr = `function (){
this.methods.log(Date.now())
}`
const myFunc = eval(myFuncStr)

Related

Change in builtin objects of JavaScript IntelliSense inside VSCode does not show

When I add a function to the Math object, it does not show inside IntelliSense of VSCode.
Math.dot = function (a,b) {};
If you don't have one already, create a type declaration module file (Ex. index.d.ts) in the root of your project folder, and add to it the following:
declare interface Math {
doc: (a:number, b:number) => number;
}
You can read more about type declaration module files in the official docs at https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html.
In simpler cases, you can just use JS Doc comments, since a basic subset of JS Doc comments are supported by VS Code's intellisense facilities. As far as I know, this is not one of those supported cases (declaring the type of a function on an existing global object).

Babel plugin - How to transform JSX without react

I have wrote my own module which takes a JSX string as a parameter and turns it into a javascript object, so I call it like so:
import parser from 'own-parser'
console.log(parser("<h1>Hello world</h1>"))
This works, but what I actually need is to transform the JSX into the object when it compiles, so I could write it like a normal JSX expression:
var jsx = <h1>Hello World</h1>
and get the result from my function as output like so:
var jsx = {element: 'h1', children:[/*...*/]}
I undrestand there are many babel plugins like "babel-plugin-transform-jsx" which can accomplish this, but I want to learn about babel plugins and how they work so I can make my own.
I've tried to analize the code of the plugin mentioned above but still cannot understand how things work, for example, how does the plugin know that he is working with a JSXElement?
The only thing I am trying to do is to extract that JSX, put it inside my function and transform it into the function's return
How can I do that? Thanks
I've figured it out, turns out you can get the code of a node with path.toString(), for example to declare a visitor like that:
JSXElement(path, state) {
if (path.parentPath.type != "JSXElement") {
const parsed = parser(path.toString())
path.replaceWithSourceString(JSON.stringify(parsed))
}
}
This is not present in the babel plugin handbook, I suppose this is a bad practice, but anyways it is a quick solution in case anyone wondered

Mock string.Format in jasmine

I am trying to write unit tests for a mobile app that has been developed in Appcelerator titanium. I am trying to unit test it with TiUnit and Jasmine.
One of my methods uses String.format(). How do I unit test that method since String.format() is not defined in Javascript?
function MyMethod(_flag, _myProperty, _propertyValue) {
if(_flag) {
_myProperty = String.format('The value :', _propertyValue);
}
}
Is it possible to mock this? Or can I add format() to the prototype of jasmine's String so that whenever it encounters format() in .js to be tested, it executes the format() which I will define in the test suite?
A way to get around this problem is to make this a pure function.
Take this small change as an example:
function MyMethod(_flag, _myProperty, _propertyValue, formatFunction) {
if(_flag) {
_myProperty = formatFunction('The value :', _propertyValue);
}
}
Now MyMethod does not have a dependency on anything external to the function. This allows you to use whatever string formatter you want, and in your case a mocked one.
In your test, you now have the ability to do something like this:
it('should format the string', () => {
const mockFormatter = () => {/*do the mock operation of your choosing here*/}
const formattedString = MyMethod(yourFlag, yourProperty, yourPropertyValue, mockFormatter)
assert(formattedString, expectedOutput)
})
What this allows is for you to not have to manipulate the global String object/prototypes, which can have implications elsewhere. Instead, you create a function that is agnostic to the formatter and are able to easily mock it.
Lastly, now that I have hopefully helped provide a path forward on your original question, I'm curious why you are after mocking the formatter? This seems like something you would always want to validate, and would have no harm in doing so. To me, and this can lead to very in depth and often pedantic discussions on testing, this already suffices as a unit test. It is not "pure", but as far as side-effects go, there are none and you are testing some basic expectations around data manipulation without.
I think mocking String.format() introduces unnecessary complexity to the test without any real gain in code-confidence.
**Edit: I assumed String.format() was a JS function I had not heard of, but that does not appear to be the case.
To achieve what you are after, and avoid the need to mock entirely, I think you should use string interpolation via string literals, or concatenation.
See here:
function MyMethod(_flag, _myProperty, _propertyValue) {
if(_flag) {
_myProperty = `The value : ${_propertyValue}`; // option 1 uses interpolation
// _myProperty = 'The value : ' + _propertyValue; // option 2 uses concatenation
}
}

Is it possible to import variables in JavaScript (node.js)?

I have variables in app.js:
var G = {};
module.exports = G;
var DATA = G.DATA = 'DATA';
var F1 = G.F1 = function(val)
{
return val;
};
In this manner, I can export variables under the object G, and at the same time, can access the variable directly writing DATA without G. prefix.
So far so good.
Now, I want to run a test for app.js in test.js:
var G = require('./app.js');
console.log(G.DATA); // -> DATA
This works, but I also want to access the variable directly writing DATA without G. prefix like console.log(DATA); // -> DATA
Surely, I could do like
var DATA = G.DATA; for every variables(property) export&required module G object, but obviously it's a tedious process to add every variable to the test file manually to correspond the G objects.
Is there any way to do this automatically?
So far, I'm pessmistic since
JS function encloses var in the own scope, so in theory there's no way to have a helper function to var for every object property.
Thanks.
PS. I would like to avoid any eval or VM of node solution. I have tried them in past, and too much problems.
I could assign a local variables for every property export&required module G object, but obviously it's a tedious process to add every variable to the test file manually to correspond the G objects.
No, that's how it is supposed to work. You - and only you - are in charge of what local variables exist in your module scope. No changes in the "export variables" of an included module should break your code.
Accessing properties on the imported module (with a self-chosen name) is the way to go. This is quite equivalent to Python's import app or import app as g.
If you want some particular properties as local variables, you will usually choose them manually, as in Python's from app import DATA, F1. In JS, you will need a multiple var statement like the one you've shown in your question. However, there is a syntax feature called destructuring assignment which will make this more fluid. You can use this in JavaScript 1.7+ (Gecko), CoffeeScript, or EcmaScript 6:
var {DATA, F1} = require("app.js");
Is there any way to do this automatically?
Yes and No. You should not do this, but you can - just like Python's frowned-upon from app import *. To cite what they say, which is equally true for JavaScript:
[It] introduces an unknown set of names into the interpreter, possibly
hiding some things you have already defined.
Note that in general the practice of importing * from a module or
package is frowned upon, since it often causes poorly readable code.
However, it is okay to use it to save typing in interactive sessions.
In JavaScript, you can[1] use the with-statement:
with (require("app.js")) {
…
}
[1]: Not in ES5.1 strict mode, though - which is recommended for optimisation

How to detect variable dependencies for a javascript function

Say I have this function:
function test(){
return a + b + 1;
}
How can I dynamically figure out that it will require globals a and b to be able to run? E.g. something like get_dependencies(test) returns ['a', 'b']
There's no built-in way to do that in standard JavaScript, if you're trying to do it with JavaScript itself.
On nearly all (but not all) JavaScript engines, you can get a form of the source of a function from the function object's toString function, e.g.:
var testSource = test.toString();
...and then of course you could parse that. This is non-standard behavior (the result of calling toString on a function is not defined in the specification), but it's widely-supported. You'd still have to do the parsing to find the symbols.
For the parsing, you have a couple of options. You could try to separate the parser portion of JSLint out of the rest of it, or alternately the terribly-named UglifyJS compressor has a full JavaScript parser which is already separate from the compressor part (see parse-js.js; apparently there's a tiny bit of NodeJS-specific stuff you might want to remove).
You can use a Javascript 'lint' tool that will test your code for common mistakes or oddities.
Some can be found online:
http://www.jslint.com/
http://www.javascriptlint.com/online_lint.php (can also be downloaded)
In your case, you might want to isolate individual functions via a regular expression for example, and submit them to such a tool.

Categories