Class inheritance - Web Core and FNC JSON Persistence - range error

When trying to export a simple object I get a range error: RangeError: buffer length for Uint16Array should be a multiple of 2

Here is a reproducable minimal:
WebCylinderBoolean.zip (5.9 KB)

Review the class hierarchy in the test project above, for me it consistently fails on odd and short versions of the cylinder. (all versions should work, they are just descendants)

Changing the CylinderNumber randomly will generate / resolve the range error, but not consistently.

I believe this is a valid test scenario, but if you see something wrong, let me know.
Thank you,
Neil

Hi Neil,

It's an issue in the WEBLib.TMSFNCPersistence unit. Please add the TEncoding.UTF8 as a workaround, until we patched the code and released an update. This should be the correct code:

class procedure TTMSFNCObjectPersistence.LoadObjectFromString(AObject: TObject; AString: string);
var
  ms: TStringStream;
begin
  ms := TStringStream.Create(AString{$IFDEF WEBLIB}, TEncoding.UTF8{$ENDIF});
  try
    TTMSFNCPersistence.LoadSettingsFromStream(AObject, ms);
  finally
    ms.Free;
  end;
end;

class function TTMSFNCObjectPersistence.SaveObjectToString(
  AObject: TObject): string;
var
  ss: TStringStream;
begin
  ss := TStringStream.Create(''{$IFDEF WEBLIB}, TEncoding.UTF8{$ENDIF});
  try
    TTMSFNCPersistence.SaveSettingsToStream(AObject, ss);
    ss.Position := 0;
    Result := ss.DataString;
  finally
    ss.Free;
  end;
end;

That brings some sanity and resolves the range error. Thanks for the quick fix.

It looks to me when the boolean is set, it casts as a variant and that is why the assert statements fail comparing true to 1.

The assert method has an over load to compare 2 boolean values.

      // fails trying to compare true to 1
      Assert.AreEqual(cyl.Fired, restore.Fired, 'check fired b 2 b');

When this is executed I get a failed test
TestCylinderFive [check fired b 2 b] (Expected = true, Actual = 1)

The compiler is casting it to boolean and I am not sure it matters, but it feels wrong. It feels like it would work in a lot of scenarios, but not in all.

Before
image

After
image

Hi Neil,

Can't seem to get this in the log, did you change the original code from the sample you attached to reproduce this? What I get is "Restore has been fired", 6 times.

Hi Pieter,

Well this is my confusion, so my explanation might not be good at all. When I was just trying to put some sanity around the error above I wrote these asserts for what I believed would be an easy sanity check, but the results raised more questions.

I just wrote a new TestMethod, attached in this proj:
The console statements confirm the assert findings in the original.

From a business object view, the restored cylinder.Fired <> source.Fired, even though the simple if comparison works, so I assume it changed to a variant.

If the boolean does not equal true, it should equal false and the last 2 checks fail. This means the boolean does not equal true or false, so it is a defect.

WebCylinderBoolean.zip (6.3 KB)

Using the same code, just execute the test for CylinderFive, the assert statements catch the error.

You are correct, the persistence unit was writing booleans as integers, but I wouldn't have thought internally this would change the initial type of the property. I suppose it makes sense as JavaScript is untyped. I have now changed this and I will upload a new build tomorrow. Thanks for the input Neil!

image

It is hard with web core, it really feels like you go crazy sometimes. It is very hard to come up with the simple test case, credit for this one goes to my wife's questions when she saw me pulling my hair out :grinning:

1 Like

:laughing:.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.