can you override the String constructor in js - javascript

I am Creating a JS library called EasyDOM and I have a function called $EasyDOM.toEasyDOM.String()
I just wanted to know if this is valid (in all major browsers). The context of the function is below, if needed:
var $EasyDom = { //there are more methods on $EasyDOM and toEasyDOM
toEasyDOM: { //but they are not relevant so I didn't post them
String(e) { //however it might be relevant to know it will
e = e + ''; //be called like this.String(e)
try{document.querySelector(e + '')}
catch(e) {return this.Array([])}
const $DOMFunctions = {/*a bunch of methods*/};
return $DOMFunctions
}
}
}

Related

How to add keyword to acorn or esprima parser

I am working on a language that transpiles to javascript and has a similar syntax. However I want to include some new type of block statements. For syntax purposes they are the same as an IfStatement. How can I get esprima or acorn to parse this program MyStatement {a=1;} without throwing an error? Its fine if it calls it an IfStatement. I would prefer not to fork esprima.
It turns out, that the plugin capabilities of acorn are not really documented. It seems like forking acorn would be the easiest route. In this case, it is as simple as searching for occurances of _if and following a similar pattern for _MyStatement.
However it is possible to write a plugin to accomplish what I was trying to do. It seems a bit of a hack, but here is the code. The basic steps are:
To exend Parse and add to the list of keywords that will be recognized by the first pass
Create a TokenType for the new keyword and add it to the Parser.acorn.keywordTypes, extend parseStatement so that it processes the new TokenType
Create a handler for the new TokenType which will add information to the Abstract Syntax Tree as required by the keyword functionality and also consume tokens using commands like this.expect(tt.parenR) to eat a '(' or this.parseExpression() to process an entire expression.
Here is the code:
var program =
`
MyStatement {
MyStatement(true) {
MyStatement() {
var a = 1;
}
}
if (1) {
var c = 0;
}
}
`;
const acorn = require("acorn");
const Parser = acorn.Parser;
const tt = acorn.tokTypes; //used to access standard token types like "("
const TokenType = acorn.TokenType; //used to create new types of Tokens.
//add a new keyword to Acorn.
Parser.acorn.keywordTypes["MyStatement"] = new TokenType("MyStatement",{keyword: "MyStatement"});
//const isIdentifierStart = acorn.isIdentifierStart;
function wordsRegexp(words) {
return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
}
var bruceware = function(Parser) {
return class extends Parser {
parse(program) {
console.log("hooking parse.");
//it appears it is necessary to add keywords here also.
var newKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this const class extends export import super";
newKeywords += " MyStatement";
this.keywords = wordsRegexp(newKeywords);
return(super.parse(program));
}
parseStatement(context, topLevel, exports) {
var starttype = this.type;
console.log("!!!hooking parseStatement", starttype);
if (starttype == Parser.acorn.keywordTypes["MyStatement"]) {
console.log("Parse MyStatement");
var node = this.startNode();
return this.parseMyStatement(node);
}
else {
return(super.parseStatement(context, topLevel, exports));
}
}
parseMyStatement(node) {
console.log("parse MyStatement");
this.next();
//In my language, MyStatement doesn't have to have a parameter. It could be called as `MyStatement { ... }`
if (this.type == tt.parenL) {
node.test = this.parseOptionalParenExpression();
}
else {
node.test = 0; //If there is no test, just make it 0 for now (note that this may break code generation later).
}
node.isMyStatement = true; //set a flag so we know that this if a "MyStatement" instead of an if statement.
//process the body of the block just like a normal if statement for now.
// allow function declarations in branches, but only in non-strict mode
node.consequent = this.parseStatement("if");
//node.alternate = this.eat(acornTypes["else"]) ? this.parseStatement("if") : null;
return this.finishNode(node, "IfStatement")
};
//In my language, MyStatement, optionally has a parameter. It can also by called as MyStatement() { ... }
parseOptionalParenExpression() {
this.expect(tt.parenL);
//see what type it is
console.log("Type: ", this.type);
//allow it to be blank.
var val = 0; //for now just make the condition 0. Note that this may break code generation later.
if (this.type == tt.parenR) {
this.expect(tt.parenR);
}
else {
val = this.parseExpression();
this.expect(tt.parenR);
}
return val
};
}
}
process.stdout.write('\033c'); //cls
var result2 = Parser.extend(bruceware).parse(program); //attempt to parse
console.log(JSON.stringify(result2,null,' ')); //show the results.

Is there a way to inject a try catch inside a function?

Maybe some of you know about AOP, in some languages using AOP can lead you to be able to inject code after, before, or while a method is executing,etc.
What I want is to apply the same in Javascript, I am currently working on a massive app which has more than 300 ajax calls, and every time I need to do some change on the catch statement on them, I have to modify them one by one which is very tedious.
What I want to do is something like :
functionName.before("try {")
functionName.after("} catch(ex){
//dostuff
}")
Is it possible? I know there are things like .call, or the arguments object inside every function..which seem pretty meta-function (AOP) functionalities.
Not with before and after, but a wrap will work:
Function.prototype.wrapTry = function(handle) {
var fn = this;
return function() {
try {
return fn.apply(this, arguments);
} catch(e) {
return handle(e);
}
};
};
Then use it like
var safeFunction = functionName.wrapTry(doStuff);
In JavaScript, functions are first-class objects. That means you can manipulate or redeclare them.
Assuming that there is a "foo" function:
var originalFoo = foo;
foo = function()
{
// "before" code.
// Call the original function.
originalFoo.apply(this, arguments);
// "after" code.
};
After that, any call to foo() will call the new function: even with parameters.
Old question but you may take a look over this https://github.com/k1r0s/kaop-ts/blob/master/docs/api.md#available-join-points
import { onException } from "kaop-ts"
import handlingException from "./somewhere"
class Something {
#onException(handlingException)
method() {
// stuff that may throw an error
}
}
I also will give a late answer in order to shed some light onto this special case that every then and now pops up as JavaScript and AOP.
Firstly, cases like the very one presented by the OP always ask for modifying already existing functionality, thus targeting closed code that sometimes is not even owned by the party that sees itself challenged from modifying the control flow of such code.
Why then, not just name it like that ... JavaScript method modification or JavaScript method modifiers.
Secondly, because of already riding the horse of terminology, altering closed functionality in JavaScript has nothing to do with Aspect-oriented Programming unless an implementation that claims to be AO provides abstraction and code-reuse levels for at least Aspect, Advice and Pointcut.
Last, for what the OP is going to achieve and what also has been the accepted answer, there does exist a a whole bunch of before, after around / wrap solutions, almost always unfortunately mentioning AO(P), and in far too many cases not taking care of the context or target which is essential to method modification.
The example I do provide uses a prototypal implementation of afterThrowing. Because JavaScript already features a standardized bind, I'm firmly convinced that Function.prototype is the right place as well for some other method-modifiers
like before, after, around, afterThrowing
and afterFinally.
// OP's example pseudo code
//
// functionName.before("try {")
//
// functionName.after("} catch(ex){
// dostuff
// }")
function doStuffAfterThrowing(exception, originalArguments) {
"use strict";
var context = this;
console.log('context : ', context);
console.log('String(exception) : ', String(exception));
console.log('originalArguments : ', originalArguments);
return "safely handled exception";
}
function doFail() {
throw (new ReferenceError);
}
function oneOutOfManyAjaxCallbacks(payload) {
doFail();
}
var jsonData = {
"foo": "foo",
"bar": "bar"
};
var someModifiedAjaxCallback = oneOutOfManyAjaxCallbacks.afterThrowing(doStuffAfterThrowing, { x: 'y' });
// does fail controlled/handled.
console.log('someModifiedAjaxCallback(jsonData) : ', someModifiedAjaxCallback(jsonData));
// does fail "Uncaught".
console.log('oneOutOfManyAjaxCallbacks(jsonData) : ', oneOutOfManyAjaxCallbacks(jsonData));
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
(function (Function) {
var
isFunction = function (type) {
return (
(typeof type == "function")
&& (typeof type.call == "function")
&& (typeof type.apply == "function")
);
},
getSanitizedTarget = function (target) {
return ((target != null) && target) || null;
}
;
Function.prototype.afterThrowing = function (handler, target) { // afterThrowing
target = getSanitizedTarget(target);
var proceed = this ;
return (isFunction(handler) && isFunction(proceed) && function () {
var ret, args = arguments;
try {
ret = proceed.apply(target, args);
} catch (exc) {
ret = handler.call(target, exc, args);
//throw exc;
}
return ret;
}) || proceed;
};
}(Function));
</script>
Having come that far one might also consider reading ...
sandwich pattern in javascript code
Can you alter a Javascript function after declaring it?

How to store variables: Privileged method, static property

Instead of just saying:
var thing = timeConsumingMethod();
I have my variable hidden in a method like so:
function _thing() {
var thing = timeConsumingMethod() );
return thing;
}
It gets called a number of times. I'm concerned that I'm made things very inefficient. I assume it calls timeConsumingMethod every time (which is unneeded, it's always the same) I call "_thing()" to get my variable.
How do I manage these types of variables in simple efficient way? Is something like this a solution?:
function _thing() {
return _thing.thing
}
_thing.thing = timeConsumingMethod();
Basically, i want the protection of a function and to (ideally0 access my variable using _thing() or something similar, but I only want timeConsumingMethod to run once.
edit: tried this, doesn't work either:
function _thingy() {
var thing = timeConsumingMethod();
}
_thingy.test = function() {
return( _thingy.thing)
}
Why not just:
function SomethingTimeConsuming() { ... }
function LazyThing(sourceFunction) {
this.sourceFunction = sourceFunction;
this.value = null;
this.Value = function() {
if ( this.value == null) this.value = sourceFunction();
return this.value;
}
}
JSFiddle: http://jsfiddle.net/YSAjJ/
Output:
[14:20:20.079] Calling time-consuming function *(1 time)

Does JavaScript have an equivalent way to implement c# style auto properties without massive overhead?

I'm curious if JavaScript has a way to bind a function when a property is changed without an enormous overhead like watching all the auto-properties with a timer, but without setting them via a function call. For example, I know you could do something like:
var c = new (function () {
this.Prop = 'test';
this.Prop_get = function (value) {
return('Prop = ' + this.Prop);
};
this.Prop_set = function (value) {
if (value != 'no') {
this.Prop = value;
}
};
})();
document.write(c.Prop_get());
document.write('<BR />');
c.Prop_set('no');
document.write(c.Prop_get());
document.write('<BR />');
c.Prop_set('yes');
document.write(c.Prop_get());
document.write('<BR />');
But I'm looking for some way to allow the following to produce the same result:
document.write(c.Prop);
document.write('<BR />');
c.Prop = 'no';
document.write(c.Prop);
document.write('<BR />');
c.Prop = 'yes';
document.write(c.Prop);
document.write('<BR />');
With any changes to the pseudoclass other than adding a timer to watch the Prop property for changes or similarly high-overhead solutions.
Any solution to this issue comes down to what it is that you need to support.
If you require IE6-IE8, it's probably more sane to resort to timers or horrible abuse of the DOM to make changes to hidden DOM objects, which will fire listenable events, etc...
There are a few blogs which have talked about their efforts to squeeze these browsers into conformity with some kind of mutation-aware library.
Results and caveats vary.
If you're talking about ES5-compliant browsers, most support "get" and "set" keywords directly inside of objects.
This might lead to even cleaner constructors/interfaces than C#, because constructors can be as simple as var a = {};, but you also get the magic-methods, rather than the Java list of getX, getY, z, and the headache of trying to remember what's a method and what's a property, when you get to the interface.
Seriously, this is kinda pretty:
var person = {
person_name : "Bob",
get name () { return this.person_name; },
set name (value) {
console.log("But my parents named me " + this.person_name + "!");
}
};
person.name;
person.name = "Mark";
But there's an issue here: person.person_name isn't private at all.
Anybody could swoop in and change that.
Not to fret -- get and set don't actually have to operate on properties of the object.
var Person = function (name, age) {
// we don't need to save these; closures mean they'll be remembered as arguments
// I'm saving them as `private_*` to illustrate
var private_name = name,
private_age = age;
var public_interface = {
get name () { return private_name; },
set name (value) { console.log("Nope!"); },
get age () { return private_age; },
set age (value) { console.log("Nope!"); },
set court_appointed_name (value) {
console.log("If I must...");
private_name = value;
}
};
return public_interface;
};
var mark = Person("Mark", 32);
mark.name; // "Mark";
mark.name = "Bubba"; // log: "Nope!";
mark.name; // "Mark";
mark.court_appointed_name = "Jim-Bob"; // log: "If I must..."
mark.name; // "Jim-Bob"
You could also force assignments to pass in objects, with auth-tokens, et cetera.
mark.name = {
value : "Jimmy Hoffa",
requested_by : system.user.id,
auth : system.user.auth.token
};
This is all fantastic, isn't it?
Why aren't we doing it?
Browser support.
Problem is this requires brand new syntax: all objects are defined as key-value pairs.
Messing with the syntax means any non-supporting browser will crash and burn unless you wrap your entire program in a try/catch (which is performance-suicide).
You could do one try-catch test, and lazy-load the awesome interface, versus fugly workarounds, at page-load, which is the right way to go about it, but now you're developing two versions of the application.
Or three versions, as case may be (new browsers, intermediate-browsers like FF3, and hacks for Ghetto_IE).
Intermediate browsers used {}.__defineGetter__ and {}.__defineSetter__.
Object.prototype.defineProperty (/.defineProperties) are the methods which instill hope of IE compatibility, until you realize that older versions of IE only supported the mutations on DOM objects (attached to the actual DOM tree), hence the headaches. Hooray.
I found the solution to this after coming across this link relating to getters and setters. Here is a generic method of applying properties to objects I put together as a result if anyone is interested in it:
Object.prototype.Property = function (name, fn) {
if (fn.hasOwnProperty('get')) { this.__defineGetter__(name, fn.get); }
else { this.__defineGetter__(name, function () { throw ('Cannot read property ' + name + '.'); }); }
if (fn.hasOwnProperty('set')) { this.__defineSetter__(name, fn.set); }
else { this.__defineSetter__(name, function () { throw ('Cannot write property ' + name + '.'); }); }
};
function C() {
var _Field = 'test';
this.Property('Field', {
get: function () {
return ('Field = ' + _Field);
},
set: function (value) {
if (value != 'no') {
_Field = value;
}
}
});
};
C.prototype.constructor = C;
var c = new C();
document.write(c.Field);
document.write('<BR />');
c.Field = 'no';
document.write(c.Field);
document.write('<BR />');
c.Field = 'yes';
document.write(c.Field);
document.write('<BR />');
Edit: A JQuery-friendly Object.prototype.Property function like the above:
Object.defineProperty(Object.prototype, 'Property', {
enumerable: false,
value: function (name, fn) {
if (fn.hasOwnProperty('get')) { this.__defineGetter__(name, fn.get); }
else { this.__defineGetter__(name, function () { throw ('Cannot read property ' + name + '.'); }); }
if (fn.hasOwnProperty('set')) { this.__defineSetter__(name, fn.set); }
else { this.__defineSetter__(name, function () { throw ('Cannot write property ' + name + '.'); }); }
}
});
And a working JSFiddle.

Is there a Javascript equivalent of Ruby's andand?

In trying to make my Javascript unobtrusive, I'm using onLoads to add functionality to <input>s and such. With Dojo, this looks something like:
var coolInput = dojo.byId('cool_input');
if(coolInput) {
dojo.addOnLoad(function() {
coolInput.onkeyup = function() { ... };
});
}
Or, approximately equivalently:
dojo.addOnLoad(function() {
dojo.forEach(dojo.query('#cool_input'), function(elt) {
elt.onkeyup = function() { ... };
});
});
Has anyone written an implementation of Ruby's andand so that I could do the following?
dojo.addOnLoad(function() {
// the input's onkeyup is set iff the input exists
dojo.byId('cool_input').andand().onkeyup = function() { ... };
});
or
dojo.byId('cool_input').andand(function(elt) {
// this function gets called with elt = the input iff it exists
dojo.addOnLoad(function() {
elt.onkeyup = function() { ... };
});
});
I don't know Dojo, but shouldn't your first example read
dojo.addOnLoad(function() {
var coolInput = dojo.byId('cool_input');
if(coolInput)
coolInput.onkeyup = function() { ... };
});
Otherwise, you might end up trying to access the element before the DOM has been built.
Back to your question: In JavaScript, I'd implement andand() as
function andand(obj, func, args) {
return obj && func.apply(obj, args || []);
}
Your example could then be written as
dojo.addOnLoad(function() {
andand(dojo.byId('cool_input'), function() {
this.onkeyup = function() { ... };
});
});
which isn't really that much shorter than using the explicit if statement - so why bother?
The exact syntax you want is not possible in JavaScript. The way JavaScript executes would need to change in a pretty fundamental fashion. For example:
var name = getUserById(id).andand().name;
// ^
// |-------------------------------
// if getUserById returns null, execution MUST stop here |
// otherwise, you'll get a "null is not an object" exception
However, JavaScript doesn't work that way. It simply doesn't.
The following line performs almost exactly what you want.
var name = (var user = getUserById(id)) ? user.name : null;
But readability won't scale to larger examples. For example:
// this is what you want to see
var initial = getUserById(id).andand().name.andand()[0];
// this is the best that JavaScript can do
var initial = (var name = (var user = getUserById(id)) ? user.name : null) ? name[0] : null;
And there is the side-effect of those unnecessary variables. I use those variables to avoid the double lookup. The variables are mucking up the context, and if that's a huge deal, you can use anonymous functions:
var name = (function() {return (var user = getUserById(id)) ? user.name : null;})();
Now, the user variable is cleaned-up properly, and everybody's happy. But wow! what a lot of typing! :)
You want dojo.behavior.
dojo.behavior.add({
'#cool_input': {
onKeyUp: function(evt) { ... }
}
});
How about something like this:
function andand(elt, f) {
if (elt)
return f(elt);
return null;
}
Call like this:
andand(dojo.byId('cool_input'), function(elt) {
// this function gets called with elt = the input iff it exists
dojo.addOnLoad(function() {
elt.onkeyup = function() { ... };
});
});
As far as I know there isn't a built-in JavaScript function that has that same functionality. I think the best solution though is to query by class instead of id and use dojo.forEach(...) as you will be guaranteed a non-null element in the forEach closure.
You could always use the JavaScript equivalent:
dojo.byId('cool_input') && dojo.byId('cool_input').whateverYouWantToDo(...);
I've never used dojo, but most javascript frameworks (when dealing with the DOM) return the calling element when a method is called from the element object (poor wording, sorry). So andand() would be implicit.
dojo.addOnLoad(function() {
dojo.byId('cool_input').onkeyup(function(evt) { /*event handler code*/
});
});
For a list:
Array.prototype.andand = function(property, fn) {
if (this.filter(property).length > 0) this.map(fn);
}

Categories