Set Jmeter global javascript object - javascript

I have this simple object:
var apple = {
type: "macintosh",
color: "red",
getInfo: function(int){
return "test" + int;
}
}
In Jmeter I want to put this object into a global variable that allows me to access this object.
I tried:
vars.putObject("test",apple); (In a pre-processor, so before all the assertions)
var test = vars.getObject("test"); (In all the assertions)
But it seems that the function is casted as string and therefore I can't use it in my assertions.
How to make this work?

If you are looking for a "global" solution you need to consider JMeter Properties instead of JMeter variables, to wit use props shorthand instead of vars. As per Sharing Variables user manual chapter:
The get() and put() methods only support variables with String values, but there are also getObject() and putObject() methods which can be used for arbitrary objects. JMeter variables are local to a thread, but can be used by all test elements (not just Beanshell).
If you need to share variables between threads, then JMeter properties can be used
For example in one test element:
props.put('test', apple)
In another one (can be in another Thread Group as well)
var apple = props.get('test')
log.info(apple.getInfo(1))
Also be aware that starting from JMeter 3.1 it is recommended to use Groovy language for any form of scripting as Groovy performance is much better than other scripting options, check out Apache Groovy - Why and How You Should Use It guide for more details.

In JMeter you can use Java language which you can add Object apple
public class apple {
String type = "macintosh";
String color = "red";
public String getInfo(){
return "test";
}
};
var a = new apple();
vars.putObject("a",a);
And get it later and use its methods:
var a = vars.getObject("a");
log.info(a.getInfo());
Also you can create Java classes with groovy

Related

How to pass javascript property (name) without using hard coded String?

Example use case:
I have an object with an attribute "myProperty", having getter and setter ("Property Getters and Setters" are supported since EcmaScript 5: https://www.w3schools.com/js/js_es5.asp):
var obj = {
myProperty:'myPropertyValue',
get myProperty(){
return this.property;
},
set myProperty(value){
this.property=value;
}
};
I would like to bind that attribute to a view, which is the task of a custom function that is called bindProperty.
In order to pass the property myProperty to the function, I could do something like
bindProperty(obj, 'myProperty');
However, I would like to avoid to pass the property name as a hard coded String. Strings have the disadvantage, that they are not updated when the attribute name changes during refactoring.
If I would use
bindProperty(obj, obj.myProperty);
the function would only know the property value 'myPropertyValue' and not where the value comes from.
=>How can I pass/identify the property itself, without using a String?
A. Using reflection?
I could imagine something like
bindProperty(obj, ()=>obj.myProperty);
The function bindProperty would then have to do some reflection magic to find out the name of the attribute in the body of the lambda expression (pseudo code):
let attributeName = getNameofArgumentFromBodyOfLambdaExpression(lambda);
obj[attributeName] = 'newValue';
=>Is it possible in JavaScript to evaluate the body of the lambda expression using reflection to get the name of the property?
(I know that this can be done in .NET languages, e.g.
Private Sub BindProperty(Of T)(propertyExpression As Expression(Of Func(Of T)))
Dim propertyName As String = GetPropertyName(propertyExpression)
'...
)
B. Using complex attributes
An alternative whould be that I use wrapping property objects, having their own getters and setters. Howerver, then I would have to use the property like
obj.myProperty.set('newValue')
or
obj.myProperty('newValue') //similar to knockout observables
I still want to be able to use the great Getter/Setter feature. With other words: I want to use my properties like plain attributes:
obj.myProperty = 'newValue'
Therefore, this is not an option for me and I would prefer to use Strings instead of B.
C. Any other alternatives?
An object in javascript is more or less just a mapping of strings or symbols to values. There is no real reflection that you can call upon in the runtime environment that would enable you to move backward from the value to the property name.
If all you need is refactoring, the one way to do this would be to just configure your IDE to recognize string accessors by providing some sort of type information either via Flow or Typescript or something of that sort (the type information is likely what allows reflection to work in languages like .NET). Or you could just settle for a unique prefix like "viewable_propName" and just do simple find and replace if you need to rename.
If you are really focused on getting this to work without type information and in current ES6 syntax, you could do the following:
function getNameofPropFromVal(obj, val){
for(let prop in obj){
if(obj[prop] === val) return prop;
}
}
obj[getNameofPropFromVal(obj, obj.myProp)] = 'newVal';
Though this has shortcomings:
(1) There is no guarantee that two properties won't share the same value.
(2) It introduces unnecessary runtime overhead.
Finally, if you're willing to be cutting edge and use a transformer like babel you could use decorators for your bindProperty method. That way you can just do the binding in the object definition itself. Here is an article explaining the gist and here is the more formal ECMAScript proposal.
I just found following simple work around that might fullfill my needs:
function bindProperty(obj, lambdaExpression){
let expression = lambdaExpression.toString(); // "()=> obj.myProperty"
let subStrings = expression.split(".");
let propertyName = subStrings[1];
console.info(propertyName );
//...
}

make C# method wait for JS event to happen

Intro
I'm programming a project where C# and JavaScript code need to work together, so I decided to use CefSharp as it guarantees the latest JS features (in contrast with WebView).
The Goal
Now I need to create an async C# method which would call an async JS function and then wait for it to finish. The problem is that JavaScript doesn't have anything like the await keyword, so everything is defined in terms of events.
This is what the Javascript code looks like:
var name1 = "A";
var name2 = "B";
library.renameObject("A","B");
library.onrename = function(from, to){
if(from === "A"){
//let C# know
}
}
And the C# code should ideally be something like this:
class FooObject
{
string Name;
async Task Rename(string newName)
{
await mainFrame.EvaluateScriptAsync(#"
//The JS code
");
Name = newName;
}
}
The Problem
At first I thought using a task/promise would do the job, but after some testing I found out that it's impossible to pass objects between JS and C#.
This means that when I tried to pass TaskCompletionSource to an IJavascriptCallback, I got
System.NotSupportedException: Complex types cannot be serialized to Cef lists
Then I tried to return a Promise from the JavaScript code, but in C# I always got null.
A Bad Solution
I'm aware that using reflection, proxies and Dictionary<int, WeakRef<object>> I could provide an interface, so that any C# object could be accessed from JavaScript in a way that would be indistinguishable from using an actual JS object. The approach would be:
save (a weakref to) the C# object in the dictionary under a unique key
using Reflection create methods that take the unique key as an argument and allow reading fields and calling methods of the object
expose these methods to JavaScript using RegisterJsObject
create a Proxy that would mimic an ordinary JS object and call the exposed C# methods in the background.
The bad news with this solution is that in JavaScript there are no destructors/finalizers, so I have no control over the V8 GC. This means the C# objects would stay there forever (memory leak) or get collected by the .Net GC too early (null pointer exception).

NodeJS - Javascript create object instance from String

In my Node.Js application (server side) I have to create an object instance (that is a class, so with new MyClass()) but MyClass is a string.
Its possible to create object instance from a String ? I've see that in browser side I can use window, but here I'm on server side...
I will need this because I will now the name of the class at run time, so I can't instantiate this object in "code".
Moreover, I can have several classes that need to be created in this way.
In short, I have a configuration file that explicit this kind of class, and I need to convert this string in a real JavaScript object.
With nodejs, window is "replaced" by global. So if your class is available in the global context, you can use global["ClassName"] to fetch it.
However, if you can, you may also consider the use of a dictionary of constructors. It is generally cleaner. Here is an example.
var constructors = {
Class1: Class1,
Class2: Class2
};
var obj1 = new constructors["Class1"](args);
Do you mean
var myClass = Object.assign(new MyClass(), JSON.parse(classString));

obfuscate string literals & object keys in javascript?

I'm looking for a Javascript obfuscation tool that will be able to obfuscate specific string literals.
I have a class function like this:
function Mapper() {
var map = {};
this.put = function(name, val) {
map[name] = val;
};
this.get = function(name) {
return map[name];
};
}
And it's used like this throughout my code:
var mapper = new Mapper();
mapper.put("first", 123);
mapper.put("second", 999);
var value = mapper.get("first");
// etc...
I want to obfuscate the key names - "first", "second" - since they are only relevant during development.
I obviously need these strings to be obfuscated only where they are used in context with the mapper put() or get() methods, but this is not an issue because the keys I use are not used anywhere else in my application.
However, I don't want ALL the string literals in my app to be obfuscated. Not all string literals are used as object property keys.
I wouldn't mind manually defining a list of keys that should be obfuscated if the tool requires me to do so.
How can this be done?
Is there a way to do this with one of the commonly used obfuscation tools like Closure Compiler, YUI, unglifyjs, or anything similar?
The Closure Compiler has both a "ReplaceStrings" and support for replacing "id generators". Without more details, I would assume the id generator replacement is what you want.

Will there be a new way of managing javascript classes?

Does anyone know if structuring javascript will be changed? What I mean is to have a way to manage javascript classes into packages, like in Java. Is there already a way?
I guess you are familiar with the Java concept of naming packages after a domain you own, this way avoiding collision with the packages of other vendors. You can simulate Java packages (and avoid possible naemspace collisions) with:
if (typeof(org) == "undefined")
org = {};
if (typeof(org.mydomain) == "undefined")
org.mydomain = {};
if (typeof(org.mydomain.mypackage) == "undefined")
org.mydomain.mypackage = {};
org.mydomain.mypackage.MyClass = function (newA) {
// constructor
this.a = newA;
}
org.mydomain.mypackage.MyClass.staticMethod = function () {
// static method
return "static";
}
org.mydomain.mypackage.MyClass.prototype.method = function () {
// normal method
return a;
}
var o = new org.mydomain.mypackage.MyClass(13);
console.log(o.method());
console.log(org.mydomain.mypackage.MyClass.staticMethod());
You can even simulate Java's import if you are working in a limited scope. (Doing this in the global scope would eliminate the whole point of packaging):
function afunc() {
var MyClass = org.mydomain.mypackage.MyClass;
var o = new MyClass(33);
console.log(o.method());
console.log(MyClass.staticMethod());
}
The weakest link here is the root of our namespace, org (or com or any top level domain). An other class may use it for some other reasons. Using org_mydomain as the root instead of org.mydomain may give some safety.
Edit:
You have other possibilities for the root name too if you want to avoid using TLD as the root. If your domain name is unique enough (for example a hip misspelled one like foogz.com) you can assume that there will be no other company writing reusable JavaScript classes who will go for foogz.org or foogz.biz, so probably you will be the only foogz out there. :)
An other possibility is to append your TLD to the domain name and use that for the first tag for example: mydomainorg.packagename.ClassName.
There are no JavaScript classes. There are only Objects. You can pack a bunch of objects into a different object, and treat it like a module/namespace if you wish. (example at the end.)
Because of that, there can't be any "improvements" in the field of JavaScript classes because there aren't any, and I hope there won't ever be either. And frankly, that's for the best. Would you rather deal with insane getters/setters, static members, protected, type coercion and so on etc? Prototypal inheritance beats "Classical inheritance" by miles. It's just that JavaScript didn't have too much time to get it just right.
For amazing explanations on how JavaScript objects work, I recommend Douglas Crockfords' "On JavaScript", or some answers from our very own members.
An example of "namespacing":
var obj = {
classRoom : {...},
objectify : function() {...},
capacity : 5
};
var myClass = obj.classRoom; //access it like you access a module
var capacity = 7; //this is a global variable named capacity, so it won't tamper with obj.capacity
Check out http://joose.it, it has a great module system (library, not language extension). The 4th edition of the ECMA-262 spec has packages, and it's implemented in actionscript.
There is some speculation (e.g. by John Resig) about new features like object freezing and packages that might be added to ECMAScript Harmony (a.k.a 6th Edition).
However, I personally doubt that the language committee would consider such a drastic change to the way the language handles some of its core OO principles.
JavaScript is dynamic code in a file. All you do is load some source code and run it dynamically.
Every structuring and managing system is dynamically written and done at runtime. There are lots of ways you can manage and structure javascript code.
requirejs check define
yui check YUI.add
dojo check dojo.provide
and more
Personally I recommend requireJS as it's not tied into any framework / other libraries.

Categories

Resources