What difference between methods callAsyncJavaScript and evaluateJavaScript?
Using it with same script like:
evaluateJavaScript("document.documentElement.outerHTML.toString()")
and
callAsyncJavaScript("document.documentElement.outerHTML.toString()")
returns different results:
HTML in first, and .sucess(nil) in second...
There are 3 methods that allow to run JS from WKWebView (well, there's more signatures, but 3 principle methods):
The oldest and most primitive is evaluateJavaScript(_:completionHandler:), which allows to run arbitrary piece of code. This day and age, there's no excuse to use, as it has no benefits over the other methods.
The more modern improved version is evaluateJavaScript(_:in:in:completionHandler:) which was introduced in iOS 14. It can be used to run synchronous code. It uses a modern way to present a result - Result<Any, Error>, which allows to encapsulate any sort of result, success or failure in a single convenient to use object. But the key difference is that it allows you to specify the context of the script, which prevents conflicts between different scripts:
Executing a script in its own content world effectively gives it a separate copy of the environment variables to modify.
But neither of these functions is able to support asynchronous JavaScript code, i.e. promise. You can implement promise execution if you combine evaluateJavaScript with WKScriptMessage (e.g. as explained here), but it's very awkward. So callAsyncJavaScript(_:arguments:in:in:completionHandler:) solves that problem: you can use it to execute a Promise, without additional help of WKScriptMessage, which makes code less distributed, and easier. Here's an example of how it's done.
It also has 2 additional advantages of this method:
The first argument is no longer a function name, but functionBody, which becomes an anonymous function, and prevents the naming conflicts possible due to global scope of the function.
And also arguments are separated from the body as [String : Any], which allow us to define function body somewhere statically, and reuse it by passing the arguments (as opposed to injecting them to function body as you need with evaluateJavaScript.
So you should be using this method for executing asynchronous JS code, and you can use it for the synchronous code.
One more thing: with callAsyncJavaScript you need to remember that you are defining the function body, so if you want something returned, you need to use the word return (as opposed to evaluateJavaScript, where you defined a piece of code to run, which can have no return, unless you define a function).
Related
I am interested in functional programming, so I decided to try this approach on the scripting environment of my Google Sheets file, and you know that the scripting language is Google Apps Script, which is basically javascript. And it even supports some (if not all) ES6 syntax.
The problem is that I cannot directly run any code, for example:
let a = 4;
Logger.log(a);
I mean, I cannot run it globally, I need to define a function with any name, and then place the code inside that function, and I can run the function, so the function runs the code inside.
So, maybe you ask, "why this behavior makes a problem writing pure functional code?" well, because, as I know, two of the most important factors about pure functions are:
1) We must not use global variables/functions inside a function, instead we must pass as parameters (and then as arguments of course).
2) defining function inside a function is often not very good idea in terms of readability and organization of the code.
So, I want to define more functions (to do some stuff), not just one "main" function, and I could not find any way, any single way to write code (as a whole) without violating at least one of the two statements above.
So, I mean, I can not write anything without making at least one non-pure function.
As a user explained in the comments:
Your 1st assumption is partially incorrect. A function must not depend on global, mutable variables, but it may depend on global constants and global pure functions. However, often you rather want to pass a function dependency as an argument to obtain a more general higher order function. Your 2nd assumption is merely opinion based.
So you could, for example, define a main function to run your code as a whole while defining functions inside the main function to achieve functional programming with Apps Script.
Note: I now believe this question was based on assumptions about the javascript specification which are actually implementation specific.
I am attempting to build a runtime debugging hook system for a complex dynamic javascript application. A series of choices have let me to choose to use javascript Proxy and Reflect metaprogramming constructs to interpose function calls in the application I am debugging, wrapping all incoming functions arguments in Proxy/Reflect constructs.
The approach involves replacing high level application functions with Proxies and using traps and handlers to provide debugging functionality, ultimately passing arguments through to the application in a transparent way. All property get/set and function executions act as normal. However, by wrapping all objects and functions in Proxies allows tracing of the runtime.
I am installing this hook system into Chrome.
(Note: Please do NOT provide an answer suggesting a different methodology for debugging hooks - options have been evaluated extensively.)
The issue is that some javascript methods in the application invoke closures and pass "this" parameters. When "this" parameters are wrapped in a Proxy, the runtime fails to execute a closure, instead throwing an "Illegal Invocation" Exception.
I have tried reengineering the debugging hook system to not wrap arguments for some methods, or selectively wrap arguments. I have not been able to find a way to tell if an argument is intended to be used as a context, making code that tries this approach hardcoded to many possible methods and calling conventions. Ultimately this is too fragile to calling convention edge cases and requires too many case statements.
I have also removed the logic for wrapping arguments before passing them through. This removes the benefit from the debug hooking system, and so I have always reverted the logic to wrap all incoming arguments.
alert.apply(this, [1]);
p = new Proxy(this, {});
try {
alert.apply(p, [1]);
} catch (e) {
console.log(e);
}
This throws an "Illegal Invocation" Exception.
typeof this === 'object'
true
But it seems that contexts are objects just like everything else.
I expect that passing a Proxy() through to context should succeed in an invocation. Barring this, I would expect the type of a context to be specific enough to determine whether it should be wrapped in a Proxy() or not.
I have two questions.
(1) What are the semantics of context binding closures in javascript that would cause binding to a Proxy(context) to fail with an illegal invocation?
(2) What type of object are contexts, and how can a javascript method tell one apart from other javascript objects by inspecting its properties at runtime?
What type of object are contexts, and how can a javascript method tell one apart from other javascript objects by inspecting its properties at runtime?
There is no special type. Every object can become a context by calling a method upon it. Most objects that will become a context of a method call do have that very method as an (inherited) property, but there's no guarantee.
You cannot tell them apart.
What are the semantics of context binding in javascript that would cause binding to a Proxy(context) to fail with an illegal invocation?
When the method is a native one. In user code functions, the this context being a proxy doesn't make a difference, when you access it then it will just behave as a proxy.
The problem is native methods that expect their this argument to be a native object of the respective type. Sure, those objects are still javascript objects, but they may contain private data on internal properties as well. A proxy's target and handler references are implemented through such internal properties as well, for example - you can sometimes inspect them in the debugger. The native methods don't know to unwrap a proxy and use its target instead, they just look at the object and notice that it doesn't have the required internal properties for the method to do its job. You could've passed a plain {} as well.
Examples for such methods can be found as builtins of the ECMAScript runtime:
Map.prototype.has/get/set/…
Set.prototype.has/get/set/…
TypeArrayPrototype.slice/copyWithin/map/forEach/…
Number/String/Boolean prototype methods
But also (and even more of them) as host objects supplied by the environment:
window.alert/prompt
EventTarget.prototype.addEventListener/removeEventListener
document.createElement
Element.prototype.appendChild/remove/…
really just anything that's browser-specific
but also in other environments, like the nodejs os module
I have tried unwrapping Proxies in the right places by coding in edge cases and by blanket/heuristic policies.
I think the only reasonable approach would be to check whether the called function is a native one, and unwrap all arguments (including the this argument) for them.
Only a few native functions could be whitelisted, such as most of those on the Array.prototype which are explicitly specified in the language standard to work on arbitrary objects.
If I wanted to hook calls to functions like eval and settimeout in Javascript to get things like the code eval is going to execute and through function settimeout is going to call, where would I start?
Scenario is, I go to a webpage in chrome and i want a breakpoint set at each of these points. They may however be obsfuscated (potentially malicious) so i can't just search the source for those kinds of calls.
Wouldn't i be able to use chrome directly to do this or would i really need to create a hook into v8 to capture these calls to specific js functions?
There is no way to intercept all code execution events. You would have to modify the sources.
That said, both eval and setTimeout are just functions, installed as configurable properties on the global object. You can overwrite them with wrappers:
var original_eval = eval;
eval = function(str) {
console.log("eval was called with: " + str);
return original_eval(str);
}
Note that there is a big conceptual difference between eval and setTimeout: the former takes fresh source code, the latter can only schedule calls to existing functions (that might have been created with eval).
There is also the Function constructor, which is similar to eval.
I'm new to NodeJS and am having a little trouble understanding what types of actions/tasks are executed asynchronously vs. synchronously. The specific example that I was working through was splitting a string.
I was trying to count the number of new lines in a block of text and then print that out. The below example worked. However, I'm not entirely clear why. My basic (and likely flawed) understanding is that anything that takes time is executed asynchronously (e.g. I/O), but I don't know what types of actions count as "taking time". Does the Split() method "take time"? It has to loop through the contents of a string, and if the string is abnormally long, this could take a while, why does this execute synchronously then or is it just that the split method blocks?
My question here is specific to the split method, but if anyone could also talk about or point me in the direction of some documentation that explains what gets executed synchronously vs asynchronously, it'd really appreciated!
var array = "test\nstring\nexample".split("\n");
console.log(array.length-1);
Most operations in JavaScript itself are synchronous. The exceptions include the obvious ones such as setTimeout(), setInterval(), requestAnimationFrame(), etc. Also just because you pass in a callback does not mean the function is asynchronous (for example see some of the array methods, like array.forEach(), array.map(), array.filter(), array.some(), etc.).
Node.js (core), which builds on top of JavaScript (via the v8 engine), adds its own synchronous and asynchronous methods. However fairly early on it was decided to distinguish between the two by way of an easily visible Sync suffix to functions that perform synchronously. However, similar to JavaScript, there are some exceptions (e.g. require()). It should also be noted that userland modules (on npm for example) may have their own convention (or none at all), so for those third party modules you will need to read the documentation to be sure of the behavior of their exported functions.
Essentially JavaScript is single threaded. The best advice is to assume it is single threaded unless something suggests otherwise.
Functions that aren't synchronous tend to accept a callback parameter to be executed. Examples of these would be a jQuery.ajax call or the setTimeout function.
This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
When is JavaScript’s eval() not evil?
I know, generally using eval() is bad practice.
But for what purpose it is existed there?
What is the correct purpose of eval()?
At what situation it is better to use eval()?
eval() provides access to the JavaScript compiler and this ultimately allows for code to be executed at a later time. The arguments passed to the function are passed to the JavaScript compiler after which the code is executed.
Developers argue about the security of eval(). It is less secure, but if you're absolutely sure your input is sanitized before passing it along, then it shouldn't be a problem.
Also, the results of eval() are generally slower because the code has not yet been compiled nor cached. There's obviously going to be a performance hit for using the function.
It's also difficult to debug code that results from the use of eval() because there is little-to-no contextual information (think line numbers) about the code that is ultimately executed.
In terms of web development, one of the current most popular uses of eval() is to deserialize a JSON string usually in the context of Ajax applications; however, this isn't to say that there aren't many other uses.
eval
Evaluates a string of JavaScript code
without reference to a particular
object.
If you construct an arithmetic expression as a string, you can use eval to evaluate it at a later time. For example, suppose you have a variable x. You can postpone evaluation of an expression involving x by assigning the string value of the expression, say "3 * x + 2", to a variable, and then calling eval at a later point in your script.
Be careful when using eval
eval() is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run eval() with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension.
You might want to check this article, below is a direct quote from the page which sums up the power of eval.
The JavaScript EVAL command can be
very powerful when using dynamic
content in Web-based applications.
EVAL can reduce code and eases
interaction with data that is unknown
at load time, but there are drawbacks
to take into account.
The real power of this command is its
ability to work with data that is not
known at load time—for example,
user-entered data. As I have
mentioned, EVAL takes any string that
you provide and executes it returning
a result, if one is applicable. You
can use this to execute JavaScript
where what you are being asked to
execute is not known at load time. For
example if we have a calculation
script that takes an equation provided
by the user and returns a result, you
can use EVAL to perform the
calculation.
I don't think it's so much bad to use it as dangerous. People say don't use eval because it opens loopholes for abuse. It's OK to use it if your input is safe. It is used in Doug Crockford's JSON parser, for example, after the input has been checked using a regular expression to make sure there is no "dangerous" content.
The other reason people tell you not to use it is that if you use eval too much, people will start calling you Eval Knievel.
I was experimenting recently with the eval() command while trying to come up with a new convention for a new project.
What I wanted was this: I liked the idea of having private, public, and privileged methods, ala. Doug Crockford's article, but I wanted to be able to expose public methods/variables at the TOP of my classes instead of at the bottom as is usual.
Consider this:
var Singleton = function() {
// Private
function _one() {
// code...
}
function _two() {
// code...
}
// Public
return {
one: _one,
two: _two
};
}();
With three eval()'s (two nested inside of the main one) I was able to have this syntax:
var Singleton = function() {
// Public
var $interface = {
one: $forward,
two: $forward
};
// Private
function _one() {
// code...
}
function _two() {
// code...
}
// This does the magic
return eval($init);
}('Singleton');
And against all odds and common-sense it did work. (Note that I also wanted a way to debug my namespaces which is why you can see a string passed to the singleton. $init took care of this too.)
Anyway, I guess the point of typing all this is to say that eval() isn't necessarily the diseased runt of the JavaScript litter that should be avoided at all costs, and can be used in more ways than just on (trusted!) code sent from a server and JSON de-serializing.
(Although in my case it ended up as a mental-workout, as I had since convinced myself not to bother with private-methods/variables after all and just use a strict namespacing convention.)