Disclosure Statement: This site contains affiliate links, which means that I may receive a commission if you make a purchase using these links. As an eBay Partner, I earn from qualifying purchases.
If you find these projects useful please consider becoming a sponsor with Patreon, GitHub or Liberapay.

Eval

Post Reply
User avatar
xpert13
Posts: 39
Joined: Wed May 31, 2017 5:26 pm

Eval

Post by xpert13 »

Hello. guys.

Help me please to understand how can I use Eval method of V8Context.

First of all I need to get V8Context. When I try go use next code in main process it throw error:

Code: Select all

TCefv8ContextRef.Current.Eval(sScript, '', 1, TempValue, TempException);
The process need to be PID_BROWSER (I am right?). But how can I send message to this process and read this message?
User avatar
salvadordf
Posts: 4564
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: Eval

Post by salvadordf »

Hi,

The V8 engine runs in a separate process and you would need to send and receive messages between processes to use eval.

It's much easier to use TChromium.ExecuteJavaScript to execute a JS script.

The MiniBrowser demo has all the code necessary to execute and get the results from the scripts in the Delphi form.
User avatar
xpert13
Posts: 39
Joined: Wed May 31, 2017 5:26 pm

Re: Eval

Post by xpert13 »

It's much easier to use TChromium.ExecuteJavaScript to execute a JS script.
I know, but I need eval.
The MiniBrowser demo has all the code necessary to execute and get the results from the scripts in the Delphi form.
The MiniBrowser has too much functions and I don't understand which of them useful for me and which is not
User avatar
salvadordf
Posts: 4564
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: Eval

Post by salvadordf »

Hi,

I uploaded a separate demo called JSExtension only with the JavaScript extension code.

You should be able to call TCefv8ContextRef.Current.Eval inside the extension in uTestExtension.pas and get the results in the
TJSExtensionFrm.Chromium1ProcessMessageReceived event.

The code comments explain all the steps.
User avatar
xpert13
Posts: 39
Joined: Wed May 31, 2017 5:26 pm

Re: Eval

Post by xpert13 »

I don't need extensions but your demo code was helpful for me. The right solution in my case was:

1. Create TCefCustomRenderProcessHandler, fill MessageName and OnCustomMessage properties

Code: Select all

  FProcessHandler := TCefCustomRenderProcessHandler.Create;
  FProcessHandler.MessageName := EVAL_JS;
  FProcessHandler.OnCustomMessage := RenderProcessHandler_OnCustomMessage;
  GlobalCEFApp.RenderProcessHandler := FProcessHandler as ICefRenderProcessHandler;
2. Send to render process message with code for eval

Code: Select all

var
  msg: ICefProcessMessage;
begin
  msg := TCefProcessMessageRef.New(EVAL_JS);
  msg.ArgumentList.SetString(0, sScript);
  FChromium.SendProcessMessage(PID_RENDERER, msg);
3. Catch this message in render proccess

Code: Select all

procedure TChromiumClient.RenderProcessHandler_OnCustomMessage(const pBrowser: ICefBrowser; 
  uSourceProcess: TCefProcessId; const pMessage: ICefProcessMessage);
var
  pV8Context : ICefv8Context;
  pReturnValue : ICefv8Value;
  pException : ICefV8Exception;
begin
  if (pMessage = nil) or (pMessage.ArgumentList = nil) then exit;

  if pMessage.Name = EVAL_JS then
  begin
    pV8Context := pBrowser.MainFrame.GetV8Context;
    if pV8Context.Enter then
    begin
      pV8Context.Eval(pMessage.ArgumentList.GetString(0), '', 1, pReturnValue, pException);
      ParseEvalJsAnswer(pMessage, pBrowser, pReturnValue, pException);
      pV8Context.Exit;
    end;
  end;
end;
4. Parse the results and send message back to browser process

Code: Select all

procedure TChromiumClient.ParseEvalJsAnswer(const pMessage: ICefProcessMessage; pBrowser: ICefBrowser;
  pReturnValue : ICefv8Value; pException : ICefV8Exception);
var
  pAnswer: ICefProcessMessage;
  strResult : String;
  bGoodDataType : Boolean;
begin
  pAnswer := TCefProcessMessageRef.New(EVAL_JS);

  if (pReturnValue = nil) or (not pReturnValue.IsValid) then
  begin
    pAnswer.ArgumentList.SetBool(0, false);
    pAnswer.ArgumentList.SetString(1, pException.Message);
  end else
  begin
    bGoodDataType := True;
    if pReturnValue.IsString then strResult := pReturnValue.GetStringValue
    else if pReturnValue.IsBool   then strResult := BooleanToStr(pReturnValue.GetBoolValue)
    else if pReturnValue.IsInt    then strResult := IntToStr(pReturnValue.GetIntValue)
    else if pReturnValue.IsUInt   then strResult := IntToStr(pReturnValue.GetUIntValue)
    else if pReturnValue.IsDouble then strResult := FloatToStr(pReturnValue.GetDoubleValue)
    else bGoodDataType := False;

    if bGoodDataType then
    begin
      pAnswer.ArgumentList.SetBool(0, true);
      pAnswer.ArgumentList.SetString(1, strResult);
    end else
    begin
      pAnswer.ArgumentList.SetBool(0, false);
      pAnswer.ArgumentList.SetString(1, 'Result data type need to be string, int, uint or double!');
    end;
  end;

  pBrowser.SendProcessMessage(PID_BROWSER, pAnswer);
end;
5. And catch result message in OnProcessMessageReceived of browser process

P.S. Thank you, salvadordf, for your work and help.
Post Reply