WEB Core cannot find AnsiString???

Sounds like it. I ran across this little blurb...

from PAS2JS Transporter from Pascal to JavaScript: Delphi incompatibilities and workarounds / Sudo Null IT News

You might soon have a few new "tips and tricks" items of your own with this conversion of yours. I'm guessing it is an older Delphi project? Hopefully not too many things like this to keep tripping you up!

Yes, it is definitely an older Delphi project, in a product that I sell, which is an encrypted, protected system for upgrading microcontroller firmware in the field.

For new projects, I have indeed switched to Unicode strings, but for backward compatibility, I used the AnsiString stuff in an open source encryption and decryption unit that I didn't write myself. This code is in multiple (over a dozen different) newer versions of our Simple Upgrade Management SYSTEM (SUMS) products, which started as a Delphi 7 project. These many versions allow my customers to securely update firmware in many different microcontroller types, which is why I have to have many versions of these SUMS products.

AnsiString has worked fine in the Delphi 10.1 Berlin versions of both the Upgrade Manager program, which encrypts the hex file, and in the many versions of the bootloader program, that de-crypts the hex file and programs that into the microcontroller. Encryption is needed to protect my customers' Intellectual Property (=their firmware in the microcontroller) from theft.

I suspect that changing this uTeaSet module to use Unicode strings will require me to make new versions of every one of these SUMS products, which will cost a lot of time and therefore money.

I can certainly sympathize! You might want to look into what it uses for its encryption - maybe it uses some kind of standard algorithm that you can easily replace or augment. Or if it is open source and still supported, maybe someone has upgraded it to use Unicode strings already? Encryption has come a long way since Delphi 7.

Doing a quick search (and making a ton of assumptions, just going on uTea!) I'd guess this is a Delphi implementation of the Tiny Encryption Algorithm? There are a few implementations out there, some older using AnsiString, but some newer implementations as well.

Eg: GitHub - xxtea/xxtea-delphi: XXTEA encryption algorithm library for Delphi/FreePascal.

Sorry to bother you on a weekend, but I am having a terrible time over here. I have tried to set up a very simple test project that contains a few TWebButtons and a TWebMemo, which is similar to a Repository project I have used over the years to work out tricky code. The project looks like this when running:

ProgramStarting

I was going to use this to try some of your suggestions, but even this simple WEB Core project is not working as I expected. I initialized WebMemo1.Lines in the Object Inspector to "Starting the program.." and then expected to be able to use the following methods to add more lines of text: :slight_smile:

//*****************************************************************
// Code to manage "Results" display
//*****************************************************************

procedure TMainForm.AddToResults( nextString: String);
begin
// Appends any diagnostic strings, arriving from HIDagent's OnDisplay event,
// to our ResultsMemo display
WebMemo1.Lines.Add(nextString);
end;

procedure TMainForm.ClearBtnClick(Sender: TObject);
begin
//
// Clear & Initialize "Results" display
WebMemo1.Clear;
WebMemo1.Lines.Add('Test results: ' + DateTimeToStr(Now));
WebMemo1.Lines.Add('');
AddToResults('AddToResults used here...');
end;

//*****************************************************************
// Misc methods
//*****************************************************************

procedure TMainForm.Test1BtnClick(Sender: TObject);
var
AStr : String;
begin
//
//AStr := 'HIDagent Log file name = ' + HIDagent1.LogFile;
AStr := 'Add your Test1 code here...';
AddToResults( AStr);
end;

procedure TMainForm.Test2BtnClick(Sender: TObject);
var
AStr : String;
begin
//
AStr := 'Add your Test2 code here...';
AddToResults(AStr);
end;

When I run this and click the buttons, nothing happens. No text appears. If I set breakpoints, I don't see any definite indication in the IDE that it hit a breakpoint.

I am clearly having some major misunderstanding of how WebCore works. I feel REALLY STUPID at this point. Would you be willing to look at this small project?

The Multiform demo seems to indicate that setting breakpoints in the Delphi code is meaningless. I guess I need to debug the Javascript, right?

No problem, upload it and I'll have a look?

'Debugging JavaScript' is maybe a bit of a stretch but you'll certainly be well served by knowing a bit about the JavaScript console and a bit of the other stuff that comes with the browser developer tools, which you can get at typically by hitting F12. What's your browser of choice?

One of the most basic troubleshooting tips is to use the console.log function which works a bit like ShowMessage but you can use it to output things to the JavasScript console which is always available. Eg, in WebFormCreate, add something like:

console.log('App is running...');

Which is kind of the basic thing you're trying to do with the TWebMemo here anyway.

WC_Variant.zip (1.5 MB)

Thanks!

Here are a few things to keep in mind. Now, you're doing things a little differently than I did when I first started as I just set aside the VCL code I had and started with a blank page, copying the contents of functions and code snippets and that sort of thing that I needed, but not using the units directly as you're doing. This idea of migrating code more directly is a bit more challenging but understandable as you're trying to save time obviously by using what you've got.

  1. Your interface isn't actually wired up to the underlying code. So for example, the button onCclick events aren't tied to the procedures you've defined. So that's job #1 - get the events set in the IDE so that, when you select a button in the IDE, it is mapped to the procedure in your code.

  2. If you click on a button or other control in the IDE, the available events don't include your events. I just moved them from the "private" definition in the interface section to be just above it, and then they appeared and could be selected.

  3. The JavaScript debugger will indeed stop on the breakpoints you set. I'd use these kinds of breakpoints sparingly but that's more of a personal preference thing. The reason you've not seen evidence of this is that the code with the breakpoints hasn't been invoked. You'll know when it has. The JavaScript debugger is not at all shy when it comes to this sort of thing.

  4. You're likely to run into this more often than I do with this overall approach, but the compiler will give you clues when your code isn't being used. After wiring up some of the interface, I was still left with these messages from the compiler. Not things critical to your test, but later on when they start showing up you'll certainly want to find out why.

[Hint] Unit1.pas(25): Private method "TMainForm.EnableUserControls" is never used
[Hint] Unit1.pas(27): Private method "TMainForm.FormClose" is never used
[Hint] Unit1.pas(28): Private method "TMainForm.FormDestroy" is never used
  1. When uploading projects, you can leave out the TMSWeb, Win32, __history and __recovery folders and things will be much smaller. Kind of tedious depending on how you're creating your zip file but their contents are likely not going to be used anyway, so no point in including them. Makes the file much smaller. No big deal in this case but as your project grows this will become more of an issue.

Hope that gets you a little further along. Don't feel bad about any of this stuff. It is a completely different environment than a Delphi VCL app runs in, so there's going to be some learning along the way. And there are lots of different ways of approaching it. And porting code is going to be more challenging than starting from a blank slate, certainly. But just until you get the basics down, then all the rest of it will become immensely useful again. And waaay more fun :slight_smile:

Yes, in a rush, I had pasted OnClick stuff to the Private section instead of the Published section. Those items were removed from OnClick when I compiled, but I didn't see that at the time. I have fixed that, and now my little re-usable test project works correctly.. Thanks again for your help!

I have gotten breakpoints to work in the Firefox "debugger" tab, as well.

I have sent another question to the help request about "trouble adding menu items" in which Ken Randall had suggested using TJSValueDynArray to make an equivalent of a variant record to fix some more compile errors. The compiler or linker cannot find either TJSValueDynArray or TJSValue. I need something to put in the "uses" clause. Any suggestions?

It is declared in unit types.pas

And for JSValue, it is just JSValue without the T.

Thank you VERY MUCH, gentlemen, especially for a quick reply on a Sunday! You both deserve at LEAST a pat on the back, if not an immediate RAISE! :grin:

I also provide tech support on weekends for my customers, but sadly, so many companies do not.

You guys ROCK!

2 Likes

Sorry, but it cannot find JSValue: "[Error] Unit1.pas(8): can't find unit "JSValue"

Also, it has the following problem with a line from Ryan:
Jv:=tblX.Lookup('LevelID;Trait',V,'ImgOrder');

[Error] Unit1.pas(206): identifier not found "tblX"

Sorry, I was referring to JSValue as the type. It isn't a unit, and it is usually a type that is covered by the default units anyway, you don't need to add anything new to your uses clause. For TJSValueDynArray, you do need to add Types to your uses clause for it to be found.

var
  abc: JSValue;

In this example, I think he was just showing that a typical table lookup function uses a variant as its second parameter to pass the different kinds of values needed by the columns that are passed as the first parameter. And to do that in TMS WEB Core you'd need to use one of these TJSValueDynArray variables instead of an actual Variant that you might normally use.

But that's just an example he's providing, where tblX is referring to some kind of generic table that has a lookup function. If you're not doing a lookup on a table, then this isn't all that useful. It just happens that this is a pretty common case where Variants get used in traditional database-oriented VCL apps.

The reason this is needed is that the old Delphi 7 code I am porting to 10.1B, used a number of Variant Records, which apparently are not available in WEB CORE. Any suggestions?

Is there a way to convert the code so the variant part is just replaced with separate types in the record? Less efficient, storage-wise, certainly, but if you could see how JavaScript handles a few things, storage is likely the least of your concerns :slightly_smiling_face:

Or maybe what he was suggesting was to use a TJSValueDynArray in your record and store the different values in that? I'm no expert on any of that kind of thing (this was the first time I've even heard of TJSValueDynArray!). Happy to help work through it though.

Maybe make a new post with the kinds of records you're working with and we can figure out a more optimal approach. Be sure to include the record definition (or the relevant bits or a comparable equivalent - don't need to post anything proprietary of course), as well as some examples of the code that you use to access them. So that a new record definition can be found that will work with the existing code that uses it, or simple replacements can be found to make it more of a search/replace kind of process for you.

Yeah, I suspect I'm gonna have to work out some ideas for this. I appreciate your willingness to help, so if I cannot find a way, I'll get back to you on this, maybe tomorrow, after I noodle on this awhile. I'm sure that whatever I come up with will be less efficient than a variant record, but code size is not important on the PC side program this is porting.

The microcontrollers that the PC communicates with have limited code size, but those do not need to be updated.

Yes, and if you think about how much RAM a browser takes up all its own, and then how much a typical page consumes, and so on, we're nowhere near the situation 15 years ago where extra bytes in a record were a potential concern. Even if you have tens of thousands of records. Looking at this page in the FireFox debugger for example suggests it is currently taking up 93.66 MB. And there's not really much going on here. I'd be surprised if you had a microcontroller that had that much code being passed to it!

As Andrew said, that was just an example using a generic table.