Unexpected behavior with function composition - javascript

I'm writing a little utility function to convert strings from one word separation scheme to another. The overall project is using lodash, which I know comes with stuff like _.camelCase, but I felt it was more extensible to not leverage those scheme-conversion helpers.
The idea is that other developers can easily add their own scheme definition to the ones I already have:
const CASES = [
{name: 'lower_kebab', pattern: /^[a-z]+(_[a-z]+)*$/g,
to_arr: w=> w.split('_'),
to_str: a=> a.map(w=>w.toLowerCase()).join('_')},
{name: 'UpperCamel', pattern: /^([A-Z][a-z]*)+$/g,
to_arr: w=> w.match(/[A-Z][a-z]*/g),
to_str: a=> a.map(_.capitalize).join('')},
//...
];
So each Case needs a pattern to determine if a string is of that scheme, a to_arr to split the string approprioately, and a to_str to join an array of words into a string of that scheme (name is optional, but it's good to be descriptive). I've included those two becuase it's in the conversion from lower_kebab to UpperCamel where I'm getting some unexpected behavior.
I've implemented the actual conversion function like so:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/lodash/4.17.3/lodash.min.js"></script>
<script src="https://cdn.jsdelivr.net/lodash/4.17.3/lodash.fp.min.js"></script>
<script>
$(document).ready(()=>{
var CASES = [
{ name: 'lower_kebab', pattern: /^[a-z]+(_[a-z]+)*$/g,
to_arr: w=> w.split('_'),
to_str: a=> a.map(w=>w.toLowerCase()).join('_')
},
{ name: 'UpperCamel', pattern: /^([A-Z][a-z]*)+$/g,
to_arr: w=> w.match(/[A-Z][a-z]*/g),
to_str: a=> a.map(_.capitalize).join('')
},
//...
];
function convert_to(target_scheme_example){
return _.compose(
CASES.find(c=>c.pattern.test(target_scheme_example)).to_str
, str=> CASES.find(c=>c.pattern.test(str)).to_arr(str) );
}
$('#go').on('click', ()=> $('#result').text(
convert_to( $('#dst').val() )( $('#src').val() )
));
});
</script>
<p>Try "<strong>UpperCamel</strong>" to "<strong>lower_kebab</strong>" and vice-versa.</p>
<input id="dst" value="UpperCamel" placeholder="Example of target scheme">
<input id="src" value="lower_kebab" placeholder="String to convert">
<button id="go">Convert</button>
<div>
<p><strong>Result:</strong></p>
<p id="result"></p>
</div>
The "real" version lives strictly in server-side code, so all that DOM-related stuff in the snippet is purely for demonstration purposes (the "real" version also does a little error checking using _.get which I excluded here for brevity).
Here's where things get weird.
On the server side, the problem manifests as convert_to('UpCa')('activity_template') evaluating to things like "Activity_template" and "activity template". In the demo snippet, I believe the same issue is manifesting as only being able click "Convert" only once without throwing an exception.
Any thoughts? Are my RegExs a little off? Have I misunderstood how to use _.compose? If the tool were just broken, that'd be one thing, but it's really throwing me off how it works for many cases, but not all.

From the documentation on RegExp#test:
test() called multiple times on the same global regular expression instance will advance past the previous match.
This is the reason why it only works the first time: the regular expression object (pattern) maintains state resulting from the previous execution of the test method on it.
To avoid this behaviour, you could do one of the following:
Remove the g modifiers from the pattern regular expressions, since they are not necessary for the kind of matching you are trying to do, or
Use the String#match method instead, swapping the position of the string and the regular expression:
return _.compose(
CASES.find(c=>target_scheme_example.match(c.pattern)).to_str
, str=> CASES.find(c=>str.match(c.pattern)).to_arr(str) );
}

Related

What is the default “tag” function for template literals?

What is the name of the native function that handles template literals?
That is, I know that when you write tag`Foo ${'bar'}.`;, that’s just syntactic sugar for tag(['Foo ', '.'], 'bar');.¹
But what about just ​`Foo ${'bar'}.`;? I can’t just “call” (['Foo ', '.'], 'bar');. If I already have arguments in that form, what function should I pass them to?
I am only interested in the native function that implements the template literal functionality. I am quite capable of rolling my own, but the purpose of this question is to avoid that and do it “properly”—even if my implementation is a perfect match of current native functionality, the native functionality can change and I want my usage to still match. So answers to this question should take on one of the following forms:
The name of the native function to use, ideally with links to and/or quotes from documentation of it.
Links to and/or quotes from the spec that defines precisely what the implementation of this function is, so that if I roll my own at least I can be sure it’s up to the (current) specifications.
A backed-up statement that the native implementation is unavailable and unspecified. Ideally this is backed up by, again, links to and/or quotes from documentation, but if that’s unavailable, I’ll accept other sources or argumentation that backs this claim up.
Actually, the first argument needs a raw property, since it’s a TemplateStringsArray rather than a regular array, but I’m skipping that here for the sake of making the example more readable.
Motivation
I am trying to create a tag function (tag, say) that, internally, performs the default template literal concatenation on the input. That is, I am taking the TemplateStringsArray and the remaining arguments, and turning them into a single string that has already had its templating sorted out. (This is for passing the result into another tag function, otherTag perhaps, where I want the second function to treat everything as a single string literal rather than a broken up template.)
For example, tag`Something ${'cooked'}.`; would be equivalent to otherTag`Something cooked.`;.
My current approach
The definition of tag would look something like this:
function tag(textParts, ...expressions) {
const cooked = // an array with a single string value
const raw = // an array with a single string value
return otherTag({ ...cooked, raw });
}
Defining the value of raw is fairly straightforward: I know that String.raw is the tag function I need to call here, so const raw = [String.raw(textParts.raw, ...expressions)];.
But I cannot find anywhere on the internet what function I would call for the cooked part of it. What I want is, if I have tag`Something ${'cooked'}.`;, I want const cooked = `Something ${cooked}.`; in my function. But I can’t find the name of whatever function accomplishes that.
The closest I’ve found was a claim that it could be implemented as
const cooked = [expressions.map((exp, i) => textParts[i] + exp).join('')];
This is wrong—textParts may be longer than expressions, since tag`Something ${'cooked'}.`; gets ['Something ', '.'] and ['cooked'] as its arguments.
Improving this expression to handle that isn’t a problem:
const cooked = [
textParts
.map((text, i) => (i > 0 ? expressions[i-1] : '') + text)
.join(''),
];
But that’s not the point—I don’t want to roll my own here and risk it being inconsistent with the native implementation, particularly if that changes.
The name of the native function to use, ideally with links to and/or quotes from documentation of it.
There isn't one. It is syntax, not a function.
Links to and/or quotes from the spec that defines precisely what the implementation of this function is, so that if I roll my own at least I can be sure it’s up to the (current) specifications.
Section 13.2.8 Template Literals of the specification explains how to process the syntax.

Intellij Javascript multiline structural search and replace

In our project a lot of angular unit tests contain following syntax:
inject(['dependency1', 'dependency2', function(_dependency1_, _dependency2_) {
dependency1 = _dependency1_;
dependency2 = _dependency2_;
}]);
In tests the array which lists the dependencies with string values is obsolete, since this is only useful when using minification. So we issued a coding convention to change this syntax to:
inject(function(_dependency1_, _dependency2_) {
dependency1 = _dependency1_;
dependency2 = _dependency2_;
});
Now I've been replacing a couple of these in existing code when I came across them, but I've gotten really tired of doing this manually. So I'm trying to solve this in IntelliJ by using structural search and replace. This is my search template so far:
inject([$injection$, function($argument$) {
$statement$;
}]);
with occurrences:
$injection$: 1 to infinite
$argument$: 1 to infinite
$statement$: 1 to infinite
The replace template is defined as follows:
inject(function($argument$) {
$statement$;
});
This does not work for the example I defined in the beginning however, it only matches and replaces correctly for a single line statement in the function body, so following example is replaced correctly:
inject(['dependency1', 'dependency2', function(_dependency1_, _dependency2_) {
dependency1 = _dependency1_;
}]);
Am I missing something? When I check out the simple if-else example on the Jetbrains website I get the feeling that this should work.
I have tried removing the semicolon behind the $statement$ variable, this didn't match multiple lines and resulted in the semicolons being removed after replacement. I've also tried applying a regex expressions to the $statement$ variable, but these didn't help either.
((.*)=(.*);\n)+
didn't match, probably because the semicolon is filtered out by the IntelliJ structural search before the actual regex matching is performed.
(.*)=(.*)
matched, but it replaced with the same behaviour as without the regex.
Matching multiple statements with a variable in JavaScript is currently broken because of a bug.

Translating conditional statements in string format to actual logic

I have a good knowledge of real time graphics programming and web development, and I've started a project that requires me to take a user-created conditional string and actually use those conditions in code. This is an entirely new kind of programming problem for me.
I've tried a few experiments using loops and slicing up the conditional string...but I feel like I am missing some kind of technique that would make this more efficient and straightforward. I have a feeling regular expressions may be useful here, but perhaps not.
Here is an example string:
"IF#VAR#>=2AND$VAR2$==1OR#VAR3#<=3"
The values for those actual variables will come from an array of objects. Also, the different marker symbols around the variables denote different object arrays where the actual value can be found (variable name is an index).
I have complete control over how the conditional string is formatted (adding symbols around IF/ELSE/ELSEIF AND/OR
well as special symbols around the different operands) so my options are fairly open. How would you approach such a programming problem?
The problem you're facing is called parsing and there are numerous solutions to it. First, you can write your own "interpreter" for your mini-language, including lexer (which splits the string into tokens), parser (which builds a tree structure from a stream of tokens) and executor, which walks the tree and computes the final value. Or you can use a parser generator like PEG and have the whole thing built for you automatically - you just provide the rules of your language. Finally, you can utilize javascript built-in parser/evaluator eval. This is by far the simplest option, but eval only understands javascript syntax - so you'll have to translate your language to javascript before eval'ing it. And since eval can run arbitrary code, it's not for use in untrusted environments.
Here's an example on how to use eval with your sample input:
expr = "#VAR#>=2AND$VAR2$==1OR#VAR3#<=3"
vars = {
"#": {"VAR":5},
"$": {"VAR2":1},
"#": {"VAR3":7}
}
expr = expr.replace(/([##$])(\w+)(\1)/g, function($0, $1, $2) {
return "vars['" + $1 + "']." + $2;
}).replace(/OR/g, "||").replace(/AND/g, "&&")
result = eval(expr) // returns true

I need a Javascript literal syntax converter/deobfuscation tools

I have searched Google for a converter but I did not find anything. Is there any tools available or I must make one to decode my obfuscated JavaScript code ?
I presume there is such a tool but I'm not searching Google with the right keywords.
The code is 3 pages long, this is why I need a tools.
Here is an exemple of the code :
<script>([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[(!![]+[])[!+[]+!+[]+!+[]]+(+(+[])+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+!+[]+[+[]]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]])(([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+
Thank you
This code is fascinating because it seems to use only nine characters ("[]()!+,;" and empty space U+0020) yet has some sophisticated functionality. It appears to use JavaScript's implicit type conversion to coerce arrays into various primitive types and their string representations and then use the characters from those strings to compose other strings which type out the names of functions which are then called.
Consider the following snippet which evaluates to the array filter function:
([][
(![]+[])[+[]] // => "f"
+ ([![]]+[][[]])[+!+[]+[+[]]] // => "i"
+ (![]+[])[!+[]+!+[]] // => "l"
+ (!![]+[])[+[]] // => "t"
+ (!![]+[])[!+[]+!+[]+!+[]] // => "e"
+ (!![]+[])[+!+[]] // => "r"
]) // => function filter() { /* native code */ }
Reconstructing the code as such is time consuming and error prone, so an automated solution is obviously desirable. However, the behavior of this code is so tightly bound to the JavaScript runtime that de-obsfucating it seems to require a JS interpreter to evaluate the code.
I haven't been able to find any tools that will work generally with this sort of encoding. It seems as though you'll have to study the code further and determine any patterns of usage (e.g. reliance on array methods) and figure out how to capture their usage (e.g. by wrapping high-level functions [such as Function.prototype.call]) to trace the code execution for you.
This question has already an accepted answer, but I will still post to clear some things up.
When this idea come up, some guy made a generator to encode JavaScript in this way. It is based on doing []["sort"]["call"]()["eval"](/* big blob of code here */). Therefore, you can decode the results of this encoder easily by removing the sort-call-eval part (i.e. the first 1628 bytes). In this case it produces:
if (document.cookie=="6ffe613e2919f074e477a0a80f95d6a1"){ alert("bravo"); }
else{ document.location="http://www.youtube.com/watch?v=oHg5SJYRHA0"; }
(Funny enough the creator of this code was not even able to compress it properly and save a kilobyte)
There is also an explanation of why this code doesn't work in newer browser anymore: They changed Array.prototype.sort so it does not return a reference to window. As far as I remember, this was the only way to get a reference to window, so this code is kind of broken now.

escape() doesn't seem to work consistently?

using javascript, I generate HTML code, for example adding an function which starts by clicking a link, like:
$('#myDiv').append('click');
So start() should be called if somebody hits the link (click).
TERM could contain a single word, like world or moody's, the generated HTML code would look like:
click
OR
click
As you can see, the 2nd example will not work. So i decided to "escape" the TERM, like so:
$('#myDiv').append('click');
Looking at the HTML source-code using firebug, is see, that the following code was generated:
click
Thats works fine, until I really click the link - so the browser (here firefox) seams to interpret the %27 and tries to fire start('moody's');
Is there a way to escape the term persistent without interpreting the %27 until the term is handled in JS? Is there an other solution instead of using regular expressions to change ' to \'?
Don't try to generate inline JavaScript. That way lies too much pain and maintenance hell. (If you were to go down that route, then you would escape characters in JavaScript strings with \).
Use standard event binding routines instead.
Assuming that $ is jQuery, and not one of the many other libraries that use that unhelpful variable name:
$('#myDiv').append(
$('<a>').append("click").attr('href', 'A sensible fallback').click(function (e) {
alert(TERM); // Because I don't have the function you were calling
e.preventDefault();
})
);
See also http://jsfiddle.net/TudEw/
escape() is used for url-encoding stuff, not for making it possible to put in a string literal. Your code is seriously flawed for several reasons.
If you want an onclick event, use an onclick event. Do not try to "inject" javascript code with your markup. If you have the "string" in a variable, you should never need to substitute anything in it unless you are generating urls or other restricted terms.
var element = $('<span>click</span>');
element.bind('click', function () { start(TERM); });
$('#myDiv').append(element);
If you don't know what this does, then go back to basic and learn what events and function references in javascript means.
That escape() function is for escaping url's for passing over a network, not strings. I don't know that there's a built-in function to escape strings for JavaScript, but you can try this one I found online: http://www.willstrohl.com/Blog/EntryId/67/HOW-TO-Escape-Single-Quotes-for-JavaScript-Strings.
Usage: EscapeSingleQuotes(strString)
Edit: Just noticed your note about regular expressions. This solution does use regular expressions, but I think there's nothing wrong with that :-)

Categories

Resources