How can I parse a JS file to return function name var name and it's value in a table or json using esprima? - esprima

How can I parse a example.js JS file to which has multiple functions like following examples
File : example.js
myFunction1: function (args) {
var myvar1 = "1416fd488389bd8923df5a5e9";
},
myFunction2: function (args) {
var myvar2 = "23u042scbajkabc424244u022";
}
to retun me a json like
{
"myFunction1": {
"myvar1": "1416fd488389bd8923df5a5e9"
},
"myFunction2": {
"myvar2": "23u042scbajkabc424244u022"
}
}

Related

How to pass multiple value with key to url using vue.js

I have this attributes data
for(var k = 0;k<this.form.fields.length;k++)
{
this.dynamic_fields.push({attribute_id:attributes[k].id,value: attributes[k].value})
}
this.$router.push({
path: '/api/search-temp',
query:{
attributes: this.encodedAttributes()
}
});
encodedAttributes() {
const queryAttributes =this.dynamic_fields;
if (queryAttributes) {
return typeof queryAttributes !== "string"
? btoa(JSON.stringify(queryAttributes))
: queryAttributes;
}
return "";
},
I have a attribute id and an attribute value so i want to pass this id and value to url so that i cab loop in my controller attributes array and get id and value :
localhost:8000..?attributes[]['attribute_id_1']=attributevalue1&attributes[]['attribute_id_2']=attributevalue2...
I'm redirecting like this :
this.$router.push({ path: '/search-list',query:
{
}
Issue is i want to pass this multidimentional array to url, anyother workaround for this is also highly appreciated
What you may try is to json stringify and encode the object before passing it to the $route query
function encodedAttributes() {
const queryAttributes = this.$route.query.attributes;
if (queryAttributes) {
return typeof queryAttributes !== "string"
? btoa(JSON.stringify(this.$route.query.attributes))
: queryAttributes;
}
return "";
}
function decodedAttributes() {
const attributes = this.$route.query.attributes;
if (typeof attributes === "string" && attributes.length) {
return JSON.parse(atob(attributes));
} else {
return attributes;
}
}
And pass as query parameters to the route
this.$router.push({
path: '/search-list',
query:{
attributes: this.encodedAttributes()
}
Then in the Controller you can decode the attributes value from request data to get the associated array
class MyController extends Controller
{
public function index(Request $request)
{
$request->attributes = is_array(
$requestAttributes = json_decode(base64_decode($request->attributes), true)
)
? $requestAttributes
: [];
//Do other processing as needed
}
}
Had used something similar in one of my projects can't get my hands on the code right now.
Probably you can use function to escape unicode characters in the encodedAttributes as well as decodedAttributes if need be
function escapeUnicode(str){
return str.replace(/[^\0-~]/g, c => '\\u' + ('000' + c.charCodeAt().toString(16)).slice(-4))
}
function encodedAttributes() {
const queryAttributes = this.$route.query.attributes;
if (queryAttributes) {
return typeof queryAttributes !== "string"
? btoa(escapeUnicode(JSON.stringify(this.$route.query.attributes)))
: queryAttributes;
}
return "";
}
function decodedAttributes() {
const attributes = this.$route.query.attributes;
if (typeof attributes === "string" && attributes.length) {
return JSON.parse(atob(escapeUnicode(attributes)));
} else {
return attributes;
}
}
You're trying to set a nested object to the query params, it's not possible... your route's query object must be a flat object.
Summarizing the only way for you to have something like this:
?attributes[]['attribute_id_1']=attributevalue1&attributes[]['attribute_id_2']=attributevalue2
Would be from a query object like this:
query: {
"attributes[]['attribute_id_1']": 'attributevalue1',
"attributes[]['attribute_id_2']": 'attributevalue2',
}
You should flatten this multidimensional array into an simples object and use it as your query object.
Here is an example...
From this:
const multiDimArr = [
['attribute_1', 'value1'],
['attribute_2', 'value2']
];
Into:
const myObject = {
attribute_1: 'value1',
attribute_2: 'value2'
}
A way to do so would be:
const multiDimArr = [
['attribute_1', 'value1'],
['attribute_2', 'value2']
];
const myObject = {};
multiDimArr.forEach(arr => {
myObject[arr[0]] = arr[1];
});
And then use the object as the query object, so your url will look like this:
?attribute_1=value1&attribute_2=value2

Transitioning away from Object.observe

I've been using Object.observe() as part of a nw.js project that is now transitioning from nw.js v.0.12.3 to latest.
I have code like this:
..(myclass)..
data: { a:0, b:42 },
setupHandlers: function () {
Object.observe(this.data, changes => this.draw());
},
draw: function () { .. }
My initial conversion looks like:
data: {_a: 0, _b: 42},
get a() { return this._a; }
set a(val) { this.data._a = val; this.draw(); }
get b() { return this._b; }
set b(val) { this.data._b = val; this.draw(); }
and then change every place that wrote to data (myobj.data.a = 1) to instead write to the object (myobj.a = 1), thus using the setter.
It's a very labor-intensive conversion, is there an easier way?
We ended up using Proxy to catch attribute assignment:
const shallow_observer = function (obj, fn) {
return new Proxy(obj, {
set(target, name, val) {
target[name] = val;
if (fn) fn(target, name, val);
return true;
}
});
};
which allowed us to do:
data: { a:0, b:42 },
setupHandlers: function () {
this.data = shallow_observer(this.data, (data, field, value) => this.draw());
},
draw: function () { .. }
We have a deep_observer function too (which is much more complex), that detects changes in a nested data structure, but the shallow_observer was sufficient for all our use-cases.

ElasticSearch Truncate Index TypeError

I am using mongoosastic npm module. While truncating index I am getting
TypeError: Unable to build a path with those params. Supply at least index
The code I'm using
For Truncate :
var tagModelJS = require('../DaoModel/TagModel.js');
var TagModel = tagModelJS.getTagModel();
TagModel.esTruncate(function (err) {
if (err) {
console.log("ERROR : while removing data from elastic search.")
throw err;
}
});
TagModel :
var TAGS;
module.exports = {
createSchemaAndGetModel : function (mongoose, mongoosastic, Schema) {
//create schema
var tagSchema = new Schema({
tagDetail : String,
userIds : [], //list of user ids
tagName : {
type : [String],
es_indexed : true
} // field level
});
tagSchema.plugin(mongoosastic)
//create model
TAGS = mongoose.model('TAGS', tagSchema);
console.log("Tag model ready....");
},
getTagModel : function () {
return TAGS;
}
};
Any help would be greatly appreciated.

Jasmine toEqual for complex objects (mixed with functions)

Currently, I have a function that sometimes return an object with some functions inside. When using expect(...).toEqual({...}) it doesn't seem to match those complex objects. Objects having functions or the File class (from input type file), it just can't. How to overcome this?
Try the Underscore _.isEqual() function:
expect(_.isEqual(obj1, obj2)).toEqual(true);
If that works, you could create a custom matcher:
this.addMatchers({
toDeepEqual: function(expected) {
return _.isEqual(this.actual, expected);
};
});
You can then write specs like the following:
expect(some_obj).toDeepEqual(expected_obj);
As Vlad Magdalin pointed out in the comments, making the object to a JSON string, it can be as deep as it is, and functions and File/FileList class. Of course, instead of toString() on the function, it could just be called 'Function'
function replacer(k, v) {
if (typeof v === 'function') {
v = v.toString();
} else if (window['File'] && v instanceof File) {
v = '[File]';
} else if (window['FileList'] && v instanceof FileList) {
v = '[FileList]';
}
return v;
}
beforeEach(function(){
this.addMatchers({
toBeJsonEqual: function(expected){
var one = JSON.stringify(this.actual, replacer).replace(/(\\t|\\n)/g,''),
two = JSON.stringify(expected, replacer).replace(/(\\t|\\n)/g,'');
return one === two;
}
});
});
expect(obj).toBeJsonEqual(obj2);
If anyone is using node.js like myself, the following method is what I use in my Jasmine tests when I am only concerned with comparing the simple properties while ignoring all functions. This method requires json-stable-stringify which is used to sort the object properties prior to serializing.
Usage:
var stringify = require('json-stable-stringify');
var obj1 = {
func: function() {
},
str1: 'str1 value',
str2: 'str2 value',
nest1: {
nest2: {
val1:'value 1',
val2:'value 2',
someOtherFunc: function() {
}
}
}
};
var obj2 = {
str2: 'str2 value',
str1: 'str1 value',
func: function() {
},
nest1: {
nest2: {
otherFunc: function() {
},
val2:'value 2',
val1:'value 1'
}
}
};
it('should compare object properties', function () {
expect(stringify(obj1)).toEqual(stringify(obj2));
});
Extending #Vlad Magdalin's answer, this worked in Jasmine 2:
http://jasmine.github.io/2.0/custom_matcher.html
beforeEach(function() {
jasmine.addMatchers({
toDeepEqual: function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
var result = {};
result.pass = _.isEqual(actual, expected);
return result;
}
}
}
});
});
If you're using Karma, put that in the startup callback:
callback: function() {
// Add custom Jasmine matchers.
beforeEach(function() {
jasmine.addMatchers({
toDeepEqual: function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
var result = {};
result.pass = _.isEqual(actual, expected);
return result;
}
}
}
});
});
window.__karma__.start();
});
here's how I did it using the Jasmine 2 syntax.
I created a customMatchers module in ../support/customMatchers.js (I like making modules).
"use strict";
/**
* Custom Jasmine matchers to make unit testing easier.
*/
module.exports = {
// compare two functions.
toBeTheSameFunctionAs: function(util, customEqualityTesters) {
let preProcess = function(func) {
return JSON.stringify(func.toString()).replace(/(\\t|\\n)/g,'');
};
return {
compare: function(actual, expected) {
return {
pass: (preProcess(actual) === preProcess(expected)),
message: 'The functions were not the same'
};
}
};
}
}
Which is then used in my test as follows:
"use strict";
let someExternalFunction = require('../../lib/someExternalFunction');
let thingBeingTested = require('../../lib/thingBeingTested');
let customMatchers = require('../support/customMatchers');
describe('myTests', function() {
beforeEach(function() {
jasmine.addMatchers(customMatchers);
let app = {
use: function() {}
};
spyOn(app, 'use');
thingBeingTested(app);
});
it('calls app.use with the correct function', function() {
expect(app.use.calls.count()).toBe(1);
expect(app.use.calls.argsFor(0)).toBeTheSameFunctionAs(someExternalFunction);
});
});
If you want to compare two objects but ignore their functions, you can use the methods _.isEqualWith together with _.isFunction from lodash as follows.
function ignoreFunctions(objValue, otherValue) {
if (_.isFunction(objValue) && _.isFunction(otherValue)) {
return true;
}
}
it('check object equality but ignore their functions', () => {
...
expect(_.isEqualWith(actualObject, expectedObject, ignoreFunctions)).toBeTrue();
});

jquery plugin creation issue

I have created a plugin with following codes:
var myplugin = {
init: function(options) {
$.myplugin.settings = $.extend({}, $.myplugin.defaults, options);
},
method1: function(par1) {
.....
},
method2: function(par1) {
.....
}
};
$.myplugin = function(method){
if ( myplugin[method] ) {
return myplugin[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if (typeof method === 'object' || !method) {
return myplugin.init.apply(this, arguments);
} else {
$.error( 'Method "' + method + '" does not exist in myplugin!');
}
};
$.myplugin.defaults = {
option1: 'test',
option2: '',
option3: ''
};
$.myplugin.settings = {};
$.myplugin();
This works well but the issue is that when I try to set more than 1 option and try to return its values afterwards, it gives empty; setting one option works well. For eg.
If on changing the first combo box value I call this:
$.myplugin({option1: 'first test'});
it works, but when I try to call another on second combo box it doesn't save the option, instead it reset to empty.
Is there any fix?
I would re-organize the plugin to use this structure:
var methods = {
settings: {
foo: "foo",
bar: "bar"
},
init: function(options) {
this.settings = $.extend({}, this.settings, options);
},
method1: function(par1) {
alert(this.settings.foo);
},
method2: function(par1) {
alert(this.settings.bar);
}
};
function MyPlugin(options) {
this.init(options);
return this;
}
$.extend(MyPlugin.prototype, methods);
$.myPlugin = function(options) {
return new MyPlugin(options);
}
/* usage */
// without parameters
var obj1 = $.myPlugin();
// with parameters
var obj2 = $.myPlugin({foo: "foobar"});
// each has it's own settings
obj1.method1();
obj2.method1();
Demo: http://jsfiddle.net/ypXdS/
Essentially $.myPlugin simply creates and returns a new instance of the MyPlugin class. You could get rid of it completely and use new myPlugin(options) in it's place.

Resources