tondrej / chakracore-delphi

Delphi and Free Pascal bindings and classes for Microsoft's ChakraCore library

Home Page:https://tondrej.blogspot.com/search/label/chakracore

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

EAccessViolation using Variants branch

danielrippa opened this issue · comments

commented

First, I'd like to thank you for such a great work.

Regarding the EAccessViolation:

I'm compiling using barebones freepascal on Windows:
Free Pascal Compiler version 3.2.0 [2020/06/04] for i386

Windows 10 Pro
20H2 Build 19042.685

Using code from the gist from in your October post (https://tondrej.blogspot.com/2020/10/variant-support-in-chakracore-delphi.html)

I have added a writeln at the end:

  ...
  finally
    VarClear(MyObj);
    VarClear(Json);
    Context.Free;
    Runtime.Free;
  end;
  WriteLn('After freeing.');
end.

Code runs ok:

Hello, world!
{"name":"world"}
After freeing.

But throws exceptions afterwards:

An unhandled exception occurred at $732ECF2F:
EAccessViolation: Access violation
  $732ECF2F
  $00440BF6
  $0041DF78
  $00415DF6
  $00412833

An unhandled exception occurred at $732ECF2F:
EAccessViolation: Access violation
  $732ECF2F
  $00440BF6
  $0041DF78
  $00415DF6
  $00412833
  $0040D959
  $76F771E2
  $76F771B4
  $76F63B36
  $00440BF6
  $0041DF78
  $00415DF6
  $00412833
commented

WmiSample works fine without exceptions.

Thanks for the report. I can reproduce the problem. The reason is temporary variant arrays created by invoking methods on javascript value variants. I'll try to fix it.

In the meantime, the workaround is to make sure all your variant using code gets out of scope before freeing the context and the runtime. For example:

procedure Test(Context: TChakraCoreContext);
var
  Global, Json, MyObj: Variant;
begin
  // assign javascript Global to a Variant
  Global := JsValueToVariant(Context.Global);

  // read its (JSON) property and assign it to another Variant
  Json := Global.JSON;

  // call its method, assign result to another Variant
  MyObj := Json.parse('{ "name": "world" }');

  // access property
  Writeln(Format('Hello, %s!', [MyObj.name]));

  // call another method
  Writeln(Json.stringify(MyObj));
end;

procedure Main;
var
  Runtime: TChakraCoreRuntime;
  Context: TChakraCoreContext;
begin
  Runtime := nil;
  Context := nil;
  try
    Runtime := TChakraCoreRuntime.Create;
    Context := TChakraCoreContext.Create(Runtime);
    Context.Activate;

    Test(Context);
  finally
    Context.Free;
    Runtime.Free;
  end;
  Writeln('after freeing');
end;

I've updated the gist, too.

commented

Wow. That was fast!
I confirm the workaround works fine.

Thanks!