Closed LeMoussel closed 7 years ago
Potentially, the following file will cover your desired use-case: https://github.com/AngleSharp/AngleSharp.Scripting/blob/master/AngleSharp.Scripting.JavaScript.Tests/InteractionTests.cs
Unfortunately no. All test method don't load external HTML page and insert Javascript code.
I mean, how would you do in pure JS? You would
eval
or,script
element, which references an external source.Does none of these methods work for you?
I would
If the example looks like above (where you know the script's content) I would highly recommend using eval
. As you already have access to Jint (responsible for handling the specific IDocument
) that is also most elegant.
If you need to load the script from some external source then the way you describe is certainly the best one. Here AngleSharp does all the steps for you.
So yes, that sounds good to me.
One thing to be aware is the asynchronous execution. You probably won't have access to the result right away. This is something that will definitely improve in the near future, but right now its not optimal.
I do this
var jsGetTitle = javascriptService.Engine.GetJint(ashDocument).Execute("document.Title;").GetCompletionValue().AsString();
But I got exception document is not defined
.
Is window
defined? Also you probably mean document.title
as Title
is the C# variant, but title
is the JavaScript name.
I'm confused. OK for document.title
window
is not define. With
javascriptService.Engine.GetJint(ashDocument).Execute("if (typeof window === 'undefined'){console.log('object: window is not available...');}");
I got object: window is not available...
The thing is that you execute that stuff directly from Jint, without providing the right execution layer. The way JavaScript engines are built there are is a stack of so called contexts. They all provide a base context, which contains elementary JavaScript objects, such as String
, Number
, Math
, ... Then there would be a layer populated by the current instance of the Window
interface.
AngleSharp provides this window for you. Therefore I can recommend two things:
GetJint
from the engine and Execute
from Jint.Evaluate
from the engine and supply some scripting options.This should be made more convenient I guess. Perhaps some more methods may be useful here.
some progress :)
No error with Evaluate
like this
javascriptService.Engine.Evaluate("document.title;", new ScriptOptions() { Context = ashDocument.DefaultView, Document = ashDocument });
But Evaluate
has no return type (void). Like you say this should be made more convenient.
Maybe some Evaluate
methods like Execute
may be useful here.
eg :
javascriptService.Engine.Evaluate("document.title;", new ScriptOptions() { Context = ashDocument.DefaultView, Document = ashDocument }).AsString();
POC
In EngineInstance.cs, modiy RunScript
method like this
public Jint.Native.JsValue RunScript(String source)
{
_engine.EnterExecutionContext(Lexicals, Variables, _window);
Jint.Native.JsValue jsResult = _engine.Execute(source).GetCompletionValue();
_engine.LeaveExecutionContext();
return jsResult;
}
In JavaScriptEngine.cs, Add Execute
method
public Jint.Native.JsValue Execute(String source, ScriptOptions options)
{
var objectContext = options.Context;
var instance = default(EngineInstance);
if (_contexts.TryGetValue(objectContext, out instance) == false)
_contexts.Add(objectContext, instance = new EngineInstance(objectContext, _external));
return instance.RunScript(source);
}
Test
string jsGetTitle = javascriptService.Engine.Execute("document.title;", new ScriptOptions() { Context = ashDocument.DefaultView, Document = ashDocument }).AsString();
Nope, this won't happen.
Jint will always let you access the last return value on the stack. Therefore, there is no need to make such changes. Instead, an extension method is more useful.
The coupling to Jint should be as minimal as possible. Right now its already on the edge.
Hi,
Is it possible to pass Javascript code back and execute JavaScript function/method from C#?
For example :