All Blog Posts  |  Next Post  |  Previous Post

Compiling TMS WEB Core Projects with the DCC


Thursday, April 21, 2022

1. Introduction

TMS WEB Core is a framework that allows the user to write JavaScript applications with the Pascal language. Therefore the Pascal code is transpiled to JavaScript.

TMS WEB Core supports the three IDEs Embarcadero RAD Studio with Delphi, Microsoft Visual Studio Code and Lazarus.
TMS Software Delphi  Components   TMS Software Delphi  Components TMS Software Delphi  Components

This article is primarily concerned with the Delphi IDE and shows how to use hidden features to accelerate the work with the IDE.

2. Pas2JS Transpiler

TMS WEB Core uses the Pas2JS transpiler in order to convert the Pascal code to JavaScript. In the following the transpiler is abbreviated with Pas2JS.
Pas2JS is basically compatible with the Delphi language, but there are exceptions. Because of these exceptions the Delphi IDE sometimes does not work correctly with some basic features like Code Insight.

2.1. Code Insight

Code Insight is a feature of the Delphi IDE that helps the user to write his code faster. Code Insight includes Code Completion, Parameter Completion, Code Hints, Tooltip Expression, Tooltip Insight, Go To Definition, Block Completion, Class Completion and Error Insight. It can only work if the current project is a Pascal project that can be compiled with the Delphi Compiler.

2.2. Delphi Compiler

The Delphi Compiler is the so called DCC (Delphi Commandline Compiler) which normally compiles Delphi projects. In case of a TMS WEB Core project things are different. A TMS WEB Core project is compiled with Pas2JS, not with the DCC. This behavior has consequences for Code Insight, which only works for projects that can be and are compiled with the DCC.

2.3. Compiling WEB Core projects with the DCC

TMS WEB Core has a wonderful hidden feature that allows the user to compile WEB Core projects additionally with the DCC. This feature can be enabled in Tools\Options\TMS WEB\Options.

TMS Software Delphi  Components
If Show the DCC button is set to True a tool button will appear in the tool bar, which allows to toggle between the DCC and Pas2JS.

TMS Software Delphi  Components

Here, Pas2JS is enabled. A compiled project looks like the following:

TMS Software Delphi  Components

TMS Software Delphi  Components

And here the DCC is enabled:

TMS Software Delphi  Components

TMS Software Delphi  Components

TMS Software Delphi  Components

If the project is compiled with the DCC, code completion looks like this:

TMS Software Delphi  Components

2.4. Compilation Speed

Since the DCC is one of the fastest compilers in the world, it compiles much faster than Pas2JS. Hence it is a good practice to compile a WEB Core project with the DCC during coding. The user can always check with a click on Ctrl+F9 whether his code is compilable.

3. Special Language Features

Pas2JS introduces a few special language features that cannot be compiled directly with the DCC. In the following it will be shown how they can be written in a DCC compatible way.

3.1. ASM

Pas2JS allows to write plain JavaScript in so called “ASM blocks”. Here is an example:

class function TIntegerHelper.ToString(const AValue: Integer): string; assembler;
  return AValue.toString();

With the help of the internal compiler defines WEBLIB and PAS2JS you can write this code in the following way:

class function TIntegerHelper.ToString(const AValue: Integer): string;
    return AValue.toString();
  Result := IntToStr(AValue);

This code now compiles and works with the DCC and Pas2JS.

3.2. WEBLib.Utils

The counterpart of many utility functions from Delphi’s System.SysUtils unit are currently defined in the Pas2JS unit WEBLib.Utils. With the upcoming version 2.2 of Pas2JS they will be moved to SysUtils. That is why it is currently necessary to use WEBLib.Utils.

procedure TForm1.WebButton1Click(Sender: TObject);
  ShowMessage(DateToStr(Now, FormatSettings));

3.3. Namespaces

Although Pas2JS does not know the System namespace, it is allowed to use it:


This is a valid uses clause for Pas2JS and the DCC. The same can be done with the Vcl:


The supported namespaces are
  • Data
  • Datasnap
  • System
  • Vcl

3.4. Await

JavaScript applications may be asynchronous. Therefore Pas2JS supports the Await keyword. The whole mechanism is explained in this article.
The best way to write asynchronous functions in a DCC compatible way is to use the Async attribute and the generic TAwait record.

procedure MyFunction;
  lValue: Boolean;
  lValue := TAwait.Exec<Boolean>(AsyncFunction);

Now the asynchronous code is fine with the DCC.

4. Summary

I hope this article helps to write Pas2JS code in a Delphi compatible way so that all IDE features like Code Insight can be used. The other huge advantage is that the DCC is much faster than Pas2JS, which helps to reduce the so called “turnaround times”.
A last remark is that in this case the well known and often used IDE plugin ModelMaker Code Explorer also works.

Masiha Zemarai


This blog post has received 11 comments.

1. Friday, April 22, 2022 at 10:33:19 AM

Very Nice

Morango Jose

2. Friday, April 22, 2022 at 12:32:28 PM

Hi Masiha,
Thanks for the post but when I use DCC for current projects I get a lot of compiler (more that 100 in just one project) errors. It seems that this flag should be switched on when starting from zero as it is very time consuming and not practical to satisfy DCC after progressing on the project.

Borbor Mehmet Emin

3. Friday, April 22, 2022 at 6:41:27 PM

Hi Borbor,

how do the compiler errors look like? Does CodeInsight currently work for you?

Roman Kassebaum

4. Monday, April 25, 2022 at 7:23:28 AM

Hi Roman,
Half of the errors are due to await keyword (they are not DCC compatible) and rest are typecasting errors.

Borbor Mehmet Emin

5. Monday, April 25, 2022 at 12:15:22 PM

There must be more to this as I cannot see this here, for example in the demo Demo\Basics\MultiForm where I could not see a code insight problem while await() is used.
Do you have more details how we can reproduce this?

Bruno Fierens

6. Monday, April 25, 2022 at 1:52:59 PM

Hi Borbor,

as described under "3.4. Await" replace all "async" keywords with the attribute "[Async]" and use "TAwait.Exec<>" instead of "await". This approach is BTW compatible to the MMX.

Do you have an example for such a typecast?

Roman Kassebaum

7. Monday, April 25, 2022 at 4:47:53 PM

Hi Bruno,

Response := Await(XDataWebClient.RawInvokeAsync(''IUserAccountsService.Signin'', [AUsername, APassword]));
[dcc32 Error] MainModule.pas(143): E2010 Incompatible types: ''TXDataClientResponse'' and ''TJSValue''

if I code it like this there is no more complains by DCC:
Response := TAwait.Exec<TXDataClientResponse>(XDataWebClient.RawInvokeAsync(''IUserAccountsService.Signin'', [AUsername, APassword]));

So I thougth these were due to Awaits, I may be wrong.

Borbor Mehmet Emin

8. Monday, April 25, 2022 at 9:40:53 PM

Hi Borbor,

the use of "TAwait" is correct. Please don''t forget about the "[Async]" attribute.

BTW, if you use an async procedure "TAwait" makes problems. Sometimes it is easier to change the procedure into a function that simply returns true. In this case "TAwait" does always work, even without the generics.

Roman Kassebaum

9. Sunday, May 22, 2022 at 12:19:14 PM

Hi Roman,
Just noticed this and changed those procedure calls to function returning booleans, Thanks

Borbor Mehmet Emin

10. Sunday, May 22, 2022 at 3:50:05 PM

For those who read my negative comments (comment #2), now I am using DCC compile fine. I was trying to use a construct not possible with DCC.

Borbor Mehmet Emin

11. Monday, May 23, 2022 at 2:37:37 AM

Hi Borbor,

this is great to hear!

Roman Kassebaum

Add a new comment

You will receive a confirmation mail with a link to validate your comment, please use a valid email address.
All fields are required.

All Blog Posts  |  Next Post  |  Previous Post