Sign in Join
Wiki copytemporary

Pas2js Transpiler: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Pas2js Transpiler

OldNewLine
1+## About pas2js
2+
3+pas2js is a compiler/transpiler to translate programs written in Pascal (subset of Delphi/ObjFPC syntax) to JavaScript.\
4+The goal is to use strong typing, while still be able to use low level whenever you choose.\
5+The compiled Pascal functions can be used in DOM events or called by JavaScript.\
6+pas2js is written completely in FPC, runs on many platforms like Windows, Mac and Linux and more. It is built modular consisting of the following parts:
7+
8+- file cache - loading, caching files, converting to UTF-8
9+- file resolver - handling search paths, finding used units and include files
10+- scanner - reading tokens, handling compiler directives like \$IfDef and \$Include
11+- parser - reading the tokens, checking syntax, creating Pascal nodes
12+- resolver - resolving references, type checking and checking duplicate identifiers
13+- use analyzer - finding unused identifiers, emit hints and warning
14+- converter - translating Pascal nodes into JavaScript nodes
15+- compiler - handling config files, parameters, compiling recursively all used units, writes js
16+- command line interface - a small wrapper to embed the compiler into a console program
17+- library and interface - a small wrapper to embed the compiler into a library
18+
19+Each part is tested separately and is used by other FPC tools as well. For example the scanner and parser are used by fpdoc too. Thus they are tested and extended by other programmers, reducing greatly the work for developing pas2js. Consistency is kept by several test suites, containing thousands of tests.
20+
21+</div>
22+
23+<div class="section">
24+
25+Note: The modular structure allows to compile any parts or the whole compiler into an IDE addon (not yet started).
26+
27+</div>
28+
29+<div class="section">
30+
31+## Command line parameters
32+
33+Most parameters work the same as their FPC equivalent. pas2js has some options of its own (see -J options).
34+
35+
36+ Options:
37+ Put + after a boolean switch option to enable it, - to disable it
38+ @<x> : Read compiler options from file <x> in addition to the default
39+ pas2js.cfg
40+ -B : Rebuild all
41+ -d<x> : Defines the symbol <x>. Optional: -d<x>:=<value>
42+ -i<x> : Write information and halt. <x> is a combination of the following:
43+ -iD : Write compiler date
44+ -iSO : Write compiler OS
45+ -iSP : Write compiler host processor
46+ -iTO : Write target platform
47+ -iTP : Write target processor
48+ -iV : Write short compiler version
49+ -iW : Write full compiler version
50+ -ic : Write list of supported JS processors usable by -P<x>
51+ -im : Write list of supported modeswitches usable by -M<x>
52+ -io : Write list of supported optimizations usable by -Oo<x>
53+ -it : Write list of supported targets usable by -T<x>
54+ -iJ : Write list of supported JavaScript identifiers -JoRTL-<x>
55+ -C<x> : Code generation options. <x> is a combination of the following
56+ letters:
57+ o : Overflow checking of integer operations
58+ r : Range checking
59+ R : Object checks. Verify method calls and object type casts.
60+ -F... Set file names and paths:
61+ -Fe<x>: Redirect output to file <x>. UTF-8 encoded.
62+ -FE<x>: Set main output path to <x>
63+ -Fi<x>: Add <x> to include paths
64+ -FN<x>: add <x> to namespaces. Namespaces with trailing - are removed.
65+ Delphi calls this flag "unit scope names".
66+ -Fu<x>: Add <x> to unit paths
67+ -FU<x>: Set unit output path to <x>
68+ -I<x> : Add <x> to include paths, same as -Fi
69+ -J... Extra options of pas2js
70+ -Ja<x>: Append JS file <x> to main JS file. E.g. -Jamap.js. Can be given
71+ multiple times. To remove a file name append a minus, e.g.
72+ -Jamap.js-.
73+ -Jc : Write all JavaScript concatenated into the output file
74+ -Je<x>: Encode messages as <x>.
75+ -Jeconsole: Console codepage. This is the default.
76+ -Jesystem : System codepage. On non Windows console and system are the
77+ same.
78+ -Jeutf-8 : Unicode UTF-8. Default when using -Fe.
79+ -JeJSON : Output compiler messages as JSON. Logo etc are outputted
80+ as-is.
81+ -Ji<x>: Insert JS file <x> into main JS file. E.g. -Jirtl.js. Can be given
82+ multiple times. To remove a file name append a minus, e.g.
83+ -Jirtl.js-.
84+ -Jl : lower case identifiers
85+ -Jm : generate source maps
86+ -Jmsourceroot=<x>: use x as "sourceRoot", prefix URL for source file
87+ names.
88+ -Jmbasedir=<x>: write source file names relative to directory x, default
89+ is map file folder.
90+ -Jminclude: include Pascal sources in source map.
91+ -Jmabsolute: store absolute filenames, not relative.
92+ -Jmxssiheader: start source map with XSSI protection )]}', default.
93+ -Jm-: disable generating source maps
94+ -Jo<x>: Enable or disable extra option. The x is case insensitive:
95+ -JoSearchLikeFPC: search source files like FPC, default: search case
96+ insensitive.
97+ -JoUseStrict: add "use strict" to modules, default.
98+ -JoCheckVersion-: do not add rtl version check, default.
99+ -JoCheckVersion=main: insert rtl version check into main.
100+ -JoCheckVersion=system: insert rtl version check into system unit init.
101+ -JoCheckVersion=unit: insert rtl version check into every unit init.
102+ -JoRTL-<y>=<z>: set RTL identifier y to value z. See -iJ.
103+ -Jr<x> Control writing of resource string file
104+ -Jrnone: Do not write resource string file
105+ -Jrunit: Write resource string file per unit with all resource strings
106+ -Jrprogram: Write resource string file per program with all used
107+ resource strings in program
108+ -JR<x> Control writing of linked resources
109+ -JRnone: Skip resource directives
110+ -JRjs: Write resources in Javascript structure
111+ -JRhtml[=filename] : Write resources as preload links in HTML file
112+ (default is projectfile-res.html)
113+ -Jpcmd<command>: Run postprocessor. For each generated js execute command
114+ passing the js as stdin and read the new js from stdout. This
115+ option can be added multiple times to call several postprocessors
116+ in succession.
117+ -Ju<x>: Add <x> to foreign unit paths. Foreign units are not compiled.
118+ -JU: This pas2js does not support PCU files
119+ -l : Write logo
120+ -M<x> : Set language mode or enable/disable a modeswitch
121+ -MDelphi: Delphi 7 compatibility mode
122+ -MObjFPC: FPC's Object Pascal compatibility mode (default)
123+ -M<x> : enable or disable modeswitch, see option -im
124+ Each mode (as listed above) enables its default set of modeswitches.
125+ Other modeswitches are disabled and need to be enabled one by another.
126+ -NS<x> : obsolete: add <x> to namespaces. Same as -FN<x>
127+ -n : Do not read the default config files
128+ -o<x> : Change main JavaScript file to <x>, "." means stdout
129+ -O<x> : Optimizations:
130+ -O- : Disable optimizations
131+ -O1 : Level 1 optimizations (quick and debugger friendly)
132+ -O2 : Level 2 optimizations (Level 1 + not debugger friendly)
133+ -Oo<x>: Enable or disable optimization. The x is case insensitive:
134+ -OoEnumNumbers[-]: write enum value as number instead of name. Default
135+ in -O1.
136+ -OoRemoveNotUsedPrivates[-]: Default is enabled
137+ -OoRemoveNotUsedDeclarations[-]: Default enabled for programs with -Jc
138+ -OoRemoveNotUsedPublished[-] : Default is disabled
139+ -OoShortRefGlobals[-]: Insert JS local var for types, modules and
140+ static functions. Default enabled in -O2
141+ -P<x> : Set target processor. Case insensitive:
142+ -Pecmascript5: default
143+ -Pecmascript6
144+ -S<x> : Syntax options. <x> is a combination of the following letters:
145+ 2 : Same as -Mobjfpc (default)
146+ a : Turn on assertions
147+ c : Support operators like C (*=,+=,/= and -=)
148+ d : Same as -Mdelphi
149+ j : Allows typed constants to be writeable (default)
150+ m : Enables macro replacements
151+ -SI<x> : Set interface style to <x>
152+ -SIcom : COM, reference counted interface (default)
153+ -SIcorba: CORBA interface
154+ -T<x> : Set target platform
155+ -Tbrowser: default
156+ -Tnodejs : add pas.run(), includes -Jc
157+ -Telectron: experimental
158+ -Tmodule : add pas.run(), includes -Jc
159+ -u<x> : Undefines the symbol <x>
160+ -v<x> : Be verbose. <x> is a combination of the following letters:
161+ e : Show errors (default)
162+ w : Show warnings
163+ n : Show notes
164+ h : Show hints
165+ i : Show info
166+ l : Show line numbers, needs -vi
167+ a : Show everything
168+ 0 : Show nothing (except errors)
169+ b : Show file names with full path
170+ c : Show conditionals
171+ t : Show tried/used files
172+ d : Show debug notes and info, enables -vni
173+ q : Show message numbers
174+ x : Show used tools
175+ v : Write pas2jsdebug.log with lots of debugging info
176+ z : Write messages to stderr, -o. still uses stdout.
177+ -vm<x>,<y>: Do not show messages numbered <x> and <y>.
178+ -? : Show this help
179+ -h : Show this help
180+
181+ Environment variable PAS2JS_OPTS is parsed after default config and before
182+ command line parameters.
183+
184+## Delphi and ObjFPC mode
185+
186+### Delphi mode
187+
188+- Defines macro *DELPHI*
189+- Assigning a function to a function type variable does not require the @ operator. For example, you can write either *OnGetThing:=GetValue;* or *OnGetThing:=@GetValue;*.
190+- A function type variable reference without brackets is treated as a call. For example: If *OnGetThing* is a variable of type *function: integer* you can write: *If OnGetThing=3 then ;*.
191+- You must use the @@ operator to get the procedure address (i.e. JS reference) of a procedure type variable. For example instead of *If OnClick=nil then ;* you must use *if @@OnClick=nil then ;*.
192+- Every procedure/method overload needs the 'overload' modifier.
193+
194+### ObjFPC mode
195+
196+This the default mode of pas2js and is generally more strict than the Delphi mode, and allows some more operations.
197+
198+- Defines macro *OBJFPC*
199+- Assigning a function to a function type variable requires the @ operator. For example: *OnGetThing:=@GetValue;*.
200+- A function type variable always needs brackets to be called. For example: If *OnGetThing* is a variable of type *function: integer* then this is allowed: *If OnGetThing()=3 then ;*. While this gives an error: *If OnGetThing=3 then ;*.
201+- You can compare a procedure type with *nil*. For example *If OnClick=nil then ;*.
202+- You can compare a procedure type with a procedure address (i.e. JS reference). For example *If OnClick=@OnFormClick then ;*.
203+- The procedure modifier 'overload' can be omitted when all overloads are in one scope, e.g. a unit or a class. And if one procedure has such modifier all procedures with same name and in same scope are overloads as well.
204+
205+</div>
206+
207+<div class="section">
208+
209+## Translating modules
210+
211+A Pascal Program is translated into the following JavaScript structure:
212+
213+<table>
214+<thead>
215+<tr>
216+<th><p>Pascal</p></th>
217+<th><p>JavaScript Structure, not code!</p></th>
218+</tr>
219+</thead>
220+<tbody>
221+<tr>
222+<td><pre><code> Program &amp;lt;unitname&amp;gt;;
223+ Implementation
224+ [implementation section]
225+ Begin
226+ [main code]
227+ End.</code></pre></td>
228+<td><pre><code> pas.&amp;lt;program&amp;gt;={
229+ [implementation section],
230+ $main: function() {
231+ [main code]
232+ }
233+ };
234+ </code></pre></td>
235+</tr>
236+</tbody>
237+</table>
238+
239+A Pascal Unit is translated into the following JavaScript structure:
240+
241+<table>
242+<thead>
243+<tr>
244+<th>Pascal</th>
245+<th>JavaScript Structure, not code!</th>
246+</tr>
247+</thead>
248+<tbody>
249+<tr>
250+<td><code>Unit &lt;unitname&gt;;</code><br />
251+<code>Interface</code><br />
252+<code>  [interface section]</code><br />
253+<code>Implementation</code><br />
254+<code>  [implementation section]</code><br />
255+<code>Initialization</code><br />
256+<code>  [initialization section]</code><br />
257+<code>End.</code></td>
258+<td><code>pas.&lt;unitname&gt;={</code><br />
259+<code>  [interface section],</code><br />
260+<code>  $impl: {</code><br />
261+<code>    [implementation section],</code><br />
262+<code>  },</code><br />
263+<code>  $init: function() {</code><br />
264+<code>    [initialization section]</code><br />
265+<code>  }</code><br />
266+<code>};</code></td>
267+</tr>
268+</tbody>
269+</table>
270+
271+Note: The **finalization** section is not supported by pas2js.\
272+
273+</div>
274+
275+<div class="section">
276+
277+To create and initialize the units in topological order the compiler translates an Unit to the following JavaScript code:
278+
279+<table>
280+<thead>
281+<tr>
282+<th>Pascal</th>
283+<th>JavaScript</th>
284+</tr>
285+</thead>
286+<tbody>
287+<tr>
288+<td><code>Unit &lt;unitname&gt;;</code><br />
289+<code>Interface</code><br />
290+<code>  [interface section]</code><br />
291+<code>Implementation</code><br />
292+<code>  [implementation section]</code><br />
293+<code>Initialization</code><br />
294+<code>  [initialization section]</code><br />
295+<code>End.</code></td>
296+<td><code>rtl.module('&lt;unitname&gt;',</code><br />
297+<code>  ['system',...other used units of the interface section...],</code><br />
298+<code>  function(){</code><br />
299+<code>    var $mod = this;</code><br />
300+<code>    var $impl = $mod.$impl;</code><br />
301+<code>    [interface section]</code><br />
302+<code>    $mod.$implcode = function(){</code><br />
303+<code>      [implementation section]</code><br />
304+<code>    }</code><br />
305+<code>    $mod.$init = function(){</code><br />
306+<code>      [initialization section]</code><br />
307+<code>    };</code><br />
308+<code>  },</code><br />
309+<code>  [...used units of the implementation section]</code><br />
310+<code>  };</code></td>
311+</tr>
312+</tbody>
313+</table>
314+
315+Here is a more detailed example to make it more clear:
316+
317+<table>
318+<thead>
319+<tr>
320+<th>Pascal</th>
321+<th>JavaScript</th>
322+</tr>
323+</thead>
324+<tbody>
325+<tr>
326+<td><code>Unit MyModule;</code><br />
327+<code>Interface</code><br />
328+<code>Uses Sysutils;</code><br />
329+<code>var</code><br />
330+<code>  dIntf: double;</code><br />
331+<code>  sIntf: string = 'abc';</code><br />
332+<code>procedure MyIntfProc;</code><br />
333+<code>Implementation</code><br />
334+<code>Uses Classes;</code><br />
335+<code>Var dImpl:double;</code><br />
336+<code>Procedure MyIntfProc;</code><br />
337+<code>Begin</code><br />
338+<code>  dImpl:=dIntf;</code><br />
339+<code>End;</code><br />
340+<code>Procedure MyImplProc;</code><br />
341+<code>Begin</code><br />
342+<code>  dImpl:=dIntf;</code><br />
343+<code>End;</code><br />
344+<code>Initialization</code><br />
345+<code>End.</code></td>
346+<td><code>rtl.module("MyModule",</code><br />
347+<code>["System","SysUtils"],</code><br />
348+<code>function(){</code><br />
349+<code>  var $mod = this;</code><br />
350+<code>  var $impl = $mod.$impl;</code><br />
351+<code>  this.dIntf = 0.0;</code><br />
352+<code>  this.sIntf = "abc";</code><br />
353+<code>  this.MyIntfProc = function(){</code><br />
354+<code>    $impl.dImpl = $mod.dIntf;</code><br />
355+<code>  };</code><br />
356+<code>  $mod.$implcode = function(){</code><br />
357+<code>    $impl.dImpl = 0.0;</code><br />
358+<code>    $impl.MyImplProc = function() {</code><br />
359+<code>      $impl.dImpl = $mod.dIntf;</code><br />
360+<code>    };</code><br />
361+<code>  }</code><br />
362+<code>  $mod.$init = function() {</code><br />
363+<code>  };</code><br />
364+<code>},</code><br />
365+<code>["Classes"]);</code></td>
366+</tr>
367+</tbody>
368+</table>
369+
370+Notes:
371+
372+- Unit *System* is always loaded implicitely.
373+- References to other units are translated to full path. For example *TObject* is translated to *pas.system.TObject*
374+- References to dotted unitnames, aka units with namespaces are translated to *pas\["namespace.unitname"\]*.
375+
376+## Translating variables
377+
378+Variables are converted without type, because JavaScript lacks a clear type. They are however always initialized, which helps JavaScript engines to optimize.
379+
380+<table>
381+<thead>
382+<tr>
383+<th>Pascal</th>
384+<th>JavaScript</th>
385+</tr>
386+</thead>
387+<tbody>
388+<tr>
389+<td><code>Unit MyModule;</code><br />
390+<code>Interface</code><br />
391+<code>Uses Classes,Forms;</code><br />
392+<code>const</code><br />
393+<code>  c1:integer=3;</code><br />
394+<code>  c2 = 'abc';</code><br />
395+<code>  c3 = 234;</code><br />
396+<code>  c4 = 12.45;</code><br />
397+<code>  c5 = nil;</code><br />
398+<code>var</code><br />
399+<code>  v1:string;</code><br />
400+<code>  v2,v3:double;</code><br />
401+<code>  v4:byte=0;</code><br />
402+<code>  v5:TForm;</code><br />
403+<code>  v6:TIdentMapEntry;</code><br />
404+<code>  v7:string='abc';</code><br />
405+<code>  v8:char='c';</code><br />
406+<code>  v9:array of byte;</code><br />
407+<code>Implementation</code><br />
408+<code>End.</code></td>
409+<td><code>rtl.module("MyModule",</code><br />
410+<code>["System","Classes","Forms"],</code><br />
411+<code>function(){</code><br />
412+<code>  this.c1 = 3;</code><br />
413+<code>  this.c2 = "abc";</code><br />
414+<code>  this.c3 = 234;</code><br />
415+<code>  this.c4 = 12.45;</code><br />
416+<code>  this.c5 = null;</code><br />
417+<code>  this.v1 = "";</code><br />
418+<code>  this.v2 = 0.0;</code><br />
419+<code>  this.v3 = 0.0;</code><br />
420+<code>  this.v4 = 0;</code><br />
421+<code>  this.v5 = null;</code><br />
422+<code>  this.v6 = new pas.Classes.TIdentMapEntry();</code><br />
423+<code>  this.v7 = "abc";</code><br />
424+<code>  this.v8 = "c";</code><br />
425+<code>  this.v9 = [];</code><br />
426+<code>},</code><br />
427+<code>[]);</code></td>
428+</tr>
429+</tbody>
430+</table>
431+
432+Notes:
433+
434+- Type casting a *boolean* to *integer*, gives *0* for *false* and *1* for *true*.
435+- Type casting an *integer* to *boolean*, gives *false* for *0* and *true* otherwise.
436+- A **char** is translated to a JS string, because JS lacks a native char type.
437+- A **char** is a single JS char code. An UTF-16 codepoint can contain one or two **char**.
438+- **Integers overflows** at runtime differ from Delphi/FPC, due to the double format. For example adding *var i: byte = 200; ... i:=i+100;* will result in *i=300* instead of *i=44* as in Delphi/FPC. When range checking *{\$R+}* is enabled *i:=300* will raise an ERangeError.
439+- **type cast integer to integer**, e.g. *byte(aLongInt)*
440+ - with range checking enabled: error if outside range
441+ - without range checking: emulates the FPC/Delphi behaviour: e.g. *byte(value)* translates to *value & 0xff*, *shortint(value)* translates to *value & 0xff \<\<24 \>\> 24.*
442+- The **mod-operator** works 32-bit signed in JS.
443+
444+## Translating string
445+
446+Strings are translated to JavaScript strings. They are initialized with "" and are never **null**.\
447+There are no *ShortString, AnsiString or RawByteString*. *Unicodestring* and *Widestring* are alias of *String*.\
448+JavaScript strings are immutable, which means that changing a single character in a string, creates a new string. So a *s\[2\]:='c';* is a slow operation in pas2js compared to Delphi/FPC.\
449+Although pas2js creates .js files encoded as UTF-8 with BOM, JavaScript strings are UTF-16 at runtime. Keep in mind that one UTF-16 codepoint can need two *char*, and a visible glyph can need several codepoints. Same as in Delphi.
450+
451+## Translating resourcestrings
452+
453+Resourcestrings are translated to JS objects with original (org) and current value.
454+
455+<table>
456+<thead>
457+<tr>
458+<th>Pascal</th>
459+<th>JavaScript</th>
460+</tr>
461+</thead>
462+<tbody>
463+<tr>
464+<td><code>Unit MyModule;</code><br />
465+<code>Interface</code><br />
466+<code>resourcestring</code><br />
467+<code>  rsCompiler = 'pas2js';</code><br />
468+<code>var</code><br />
469+<code>  s:string;</code><br />
470+<code>Implementation</code><br />
471+<code>initialization</code><br />
472+<code>  s:=rsCompiler;</code><br />
473+<code>End.</code></td>
474+<td><code>rtl.module("test1",["System"],function () {</code><br />
475+<code>  var $mod = this;</code><br />
476+<code>  this.s = "";</code><br />
477+<code>  $mod.$resourcestrings = {rsCompiler: {org: "pas2js"}};</code><br />
478+<code>  $mod.$init = function () {</code><br />
479+<code>    $mod.s = rtl.getResStr(pas.test1,"rsCompiler");</code><br />
480+<code>  };</code><br />
481+<code>});</code></td>
482+</tr>
483+</tbody>
484+</table>
485+
486+## Translating currency
487+
488+*Currency* in Delphi/FPC is an int64 with a factor of 10000. This is translated to a double with factor 10000 and truncated.
489+
490+- *CurA := 1.12345* -\> *CurA = 11234*
491+- *CurA + CurB* -\> *CurA + CurB*
492+- *CurA * CurB* -\> *CurA * CurB/10000*
493+- *CurA / CurB* -\> *Math.floor(CurA/CurB * 10000)*
494+- *CurA ^^ CurB* -\> *Math.floor(Math.pow(CurA/10000,CurB/10000) * 10000)*
495+- *Currency + Double* -\> *Currency + (Double*10000)*
496+- *Double := Currency* -\> *Double = Currency/10000*
497+- *Currency := Double* -\> *Currency = Math.floor(Double*10000)*
498+- *JSValue := Currency* -\> *JSValue = Currency/10000*
499+- Keep in mind that a double has only 54 bits for the number, so calculating values greater than 900,719,925,474 might give a different result than in Delphi/FPC. See SysUtils.MinCurrency/MaxCurrency
500+
501+## Translating Types
502+
503+JavaScript type design has no declarative form, except for object types (so-called prototypes). That's why all the derivatives from simple Pascal types can not be translated. The compiler ensures type safety at compile time though, which is a big plus for using Pascal.\
504+Complex Pascal types (classes, records, or arrays) are translated into JavaScript objects or arrays respectively.\
505+
506+## Translating pointer
507+
508+A *pointer* is translated to a JS reference. It can be assigned a class, a class instance, a class-of, an array, a procedure var, a method var, a @proc address, a @method address, or a pointer of record. There is no pointer arithmetic, i.e. no p+1, and no typed pointers, except for pointer of record. You can find out its type using the functions *isArray*, *isClass*, *isClassRef*, *isCallback*, etc of unit *JS*.
509+
510+## Translating record type
511+
512+A record is translated to a JavaScript object.
513+
514+<table>
515+<thead>
516+<tr>
517+<th>Pascal</th>
518+<th>JS Pas2js 1.3</th>
519+<th>JS Pas2js 1.2</th>
520+</tr>
521+</thead>
522+<tbody>
523+<tr>
524+<td><code>Unit MyModule;</code><br />
525+<code>Interface</code><br />
526+<code>Type</code><br />
527+<code>  TMyRecord = Record</code><br />
528+<code>    i: integer;</code><br />
529+<code>    s: string;</code><br />
530+<code>    d: TDateTime;</code><br />
531+<code>  End;</code><br />
532+<code>Var</code><br />
533+<code>  r, s: TMyRecord;</code><br />
534+<code>Implementation</code><br />
535+<code>Initialization</code><br />
536+<code>  r.i := 123;</code><br />
537+<code>  r:=s;</code><br />
538+<code>  if r=s then ;</code><br />
539+<code>End.</code></td>
540+<td><code>rtl.module("MyModule",</code><br />
541+<code>["System"],</code><br />
542+<code>function(){</code><br />
543+<code>  var $mod = this;</code><br />
544+<code>  rtl.recNewT($mod, "TMyRecord", function() {</code><br />
545+<code>    this.i = 0;</code><br />
546+<code>    this.s = "";</code><br />
547+<code>    this.d = 0.0;</code><br />
548+<code>    this.$eq = function (b) {</code><br />
549+<code>      return (this.i == b.i) &amp;&amp;</code><br />
550+<code>         (this.s == b.i) &amp;&amp; (this.d == b.d);</code><br />
551+<code>    };</code><br />
552+<code>    this.$assign = function (s) {</code><br />
553+<code>      this.i = s.i;</code><br />
554+<code>      this.s = s.s;</code><br />
555+<code>      this.d = s.d;</code><br />
556+<code>      return this;</code><br />
557+<code>    };</code><br />
558+<code>  };</code><br />
559+<code>  this.r = this.TMyRecord.$new();</code><br />
560+<code>  $mod.$init = function() {</code><br />
561+<code>    $mod.r.i=123;</code><br />
562+<code>    $mod.r.$assign($mod.s);</code><br />
563+<code>    if ($mod.r.$eq($mod.s)) ;</code><br />
564+<code>  },</code><br />
565+<code>},</code><br />
566+<code>[]);</code></td>
567+<td><code>rtl.module("MyModule",</code><br />
568+<code>["System"],</code><br />
569+<code>function(){</code><br />
570+<code>  var $mod = this;</code><br />
571+<code>  this.TMyRecord = function(s) {</code><br />
572+<code>    if (s){</code><br />
573+<code>      this.i = s.i;</code><br />
574+<code>      this.s = s.s;</code><br />
575+<code>      this.d = s.d;</code><br />
576+<code>    } else {</code><br />
577+<code>      this.i = 0;</code><br />
578+<code>      this.s = "";</code><br />
579+<code>      this.d = 0.0;</code><br />
580+<code>    };</code><br />
581+<code>    this.$equal = function (b) {</code><br />
582+<code>      return (this.i == b.i) &amp;&amp;</code><br />
583+<code>        (this.s == b.i) &amp;&amp; (this.d == b.d);</code><br />
584+<code>    };</code><br />
585+<code>  };</code><br />
586+<code>  this.r = new this.TMyRecord();</code><br />
587+<code>  $mod.$init = function() {</code><br />
588+<code>    $mod.r.i=123;</code><br />
589+<code>    $mod.r = new $mod.TMyRecord($mod.s);</code><br />
590+<code>    if ($mod.r.$equal($mod.s)) ;</code><br />
591+<code>  },</code><br />
592+<code>},</code><br />
593+<code>[]);</code></td>
594+</tr>
595+</tbody>
596+</table>
597+
598+- The record variable creates a JavaScript object.
599+- Variant records are not supported.
600+- Supported: Assign, pass as argument, equal, not equal, array of record, pointer of record, const, default(), RTTI.
601+- Advanced record (since pas2js 1.3):
602+ - visibility private, strict private, public, default is public
603+ - methods, class methods (must be static like in Delphi/FPC)
604+ - class vars
605+ - const fields
606+ - property, class property, array property, default array property
607+ - sub types
608+ - constructor
609+ - class constructor
610+- Not yet implemented:
611+ - operator overloading
612+ - reference counted interfaces as fields
613+ - Interfaces as nested types
614+ - default non array property
615+- Until Pas2js 1.2 when assigning a record it is cloned, creating a new JS object. Since Pas2js 1.3 only values are copied, keeping the object, so pointer of record is compatible.
616+- Since record types are JS objects it is possible to typecast a record type to the JS Object, e.g. *TJSObject(TPoint)*. Note that you cannot typecast directly to a *TJSObject* descendant. You can use *TJSWindow(TJSObject(aRecord))*.
617+- A pointer of record is simply a reference.
618+ - *p:=@r* translates to *p=r*
619+ - *p^.x* becomes *p.x*.
620+ - *New(PointerOfRecord)* creates a new record
621+ - *Dispose(PointerOfRecord)* Sets the variable to null if possible.
622+- Passing a record to an untyped arguments (e.g. ''TObject.Dispatch(var Msg)'') passes the record JS object directly, not creating a temporary reference object.
623+- Typecasting RecordType(UntypedArgument) returns the argument, i.e. no conversion.
624+
625+## Translating generics
626+
627+Generics are not translated, their specializations are.
628+
629+- Specializations are created with a \$ number postfix, for example **TList\$G3**.
630+- Their RTTI name has the full name, for example **TList\<project1.TBird\>**
631+- Multiple specializations of *TList\<word\>* creates only one specialization. That is true for the whole program.
632+- Specializations are created in the unit, where the generic is defined, not where they are specialized.
633+- Important: This means that a new specialization of *TList* require a recompile of the js of unit *generics.collections*.
634+
635+## Translating functions
636+
637+<table>
638+<thead>
639+<tr>
640+<th>Pascal</th>
641+<th>JavaScript</th>
642+</tr>
643+</thead>
644+<tbody>
645+<tr>
646+<td><code>Unit MyModule;</code><br />
647+<code>Interface</code><br />
648+<code>Function DoubleIt(n: integer): integer;</code><br />
649+<code>Implementation</code><br />
650+<code>Function DoubleIt(n: integer): integer;</code><br />
651+<code>Begin</code><br />
652+<code>  Result:=2*n;</code><br />
653+<code>End;</code><br />
654+<code>End.</code></td>
655+<td><code>rtl.module("MyModule",</code><br />
656+<code>["System"],</code><br />
657+<code>function(){</code><br />
658+<code>  this.DoubleIt = function(n){</code><br />
659+<code>    Result = 0;</code><br />
660+<code>    Result = 2*n;</code><br />
661+<code>    return Result;</code><br />
662+<code>  };</code><br />
663+<code>},</code><br />
664+<code>[]);</code></td>
665+</tr>
666+</tbody>
667+</table>
668+
669+Notes:
670+
671+- Local variables become local JavaScript variables: *var l = 0;*.
672+- Local constants become JavaScript variables in the unit/program implementation section.
673+- Local types are elevated to module.
674+- Overloaded functions are given an unique name by appending \$1, \$2, ...
675+- Supported: default values, const/var/out/default, FuncName:=
676+
677+## Translating passing a parameter by reference
678+
679+JavaScript lacks passing by reference. Instead a temporary object is created with a *get* and *set* function. That means changes within the procedure are immediately visible outside, compatible with Pascal.
680+
681+<table>
682+<thead>
683+<tr>
684+<th>Pascal</th>
685+<th>JavaScript</th>
686+</tr>
687+</thead>
688+<tbody>
689+<tr>
690+<td><code>Program MyModule;</code><br />
691+<code>Procedure DoubleIt(var n: integer);</code><br />
692+<code>Begin</code><br />
693+<code>  n:=2*n;</code><br />
694+<code>End;</code><br />
695+<code>Function Doubling(n: integer): integer;</code><br />
696+<code>Begin</code><br />
697+<code>  DoubleIt(n);</code><br />
698+<code>  Result:=n;</code><br />
699+<code>End;</code><br />
700+<code>Var</code><br />
701+<code>  i: integer = 7;</code><br />
702+<code>Begin</code><br />
703+<code>  Doubling(i);</code><br />
704+<code>End.</code></td>
705+<td><code>rtl.module("program",</code><br />
706+<code>["System"],</code><br />
707+<code>function(){</code><br />
708+<code>  var $mod = this;</code><br />
709+<code>  this.i = 7;</code><br />
710+<code>  this.DoubleIt = function(n){</code><br />
711+<code>    n.set(2*n.get());</code><br />
712+<code>  };</code><br />
713+<code>  this.Doubling = function(n){</code><br />
714+<code>    var Result = 0;</code><br />
715+<code>    DoubleIt({</code><br />
716+<code>      get:function(){</code><br />
717+<code>        return n</code><br />
718+<code>      },</code><br />
719+<code>      set:function(v){</code><br />
720+<code>        n=v;</code><br />
721+<code>      }</code><br />
722+<code>    });</code><br />
723+<code>    Result = n;</code><br />
724+<code>    return n;</code><br />
725+<code>  };</code><br />
726+<code>  $mod.$main = function(){</code><br />
727+<code>    Doubling($mod.i);</code><br />
728+<code>  }</code><br />
729+<code>},</code><br />
730+<code>[]);</code></td>
731+</tr>
732+</tbody>
733+</table>
734+
735+When the passed value is from another context, the context is passed too:
736+
737+<table>
738+<thead>
739+<tr>
740+<th>Pascal</th>
741+<th>JavaScript</th>
742+</tr>
743+</thead>
744+<tbody>
745+<tr>
746+<td><code>Program MyModule;</code><br />
747+<code>Procedure DoubleIt(var n: integer);</code><br />
748+<code>Begin</code><br />
749+<code>  n:=2*n;</code><br />
750+<code>End;</code><br />
751+<code>Var</code><br />
752+<code>  i: integer = 7;</code><br />
753+<code>Begin</code><br />
754+<code>  DoubleIt(i);</code><br />
755+<code>End.</code></td>
756+<td><code>rtl.module("program",</code><br />
757+<code>["System"],</code><br />
758+<code>function(){</code><br />
759+<code>  var $mod = this;</code><br />
760+<code>  this.i = 7;</code><br />
761+<code>  this.DoubleIt = function(n){</code><br />
762+<code>    n.set(2*n.get());</code><br />
763+<code>  };</code><br />
764+<code>  $mod.$main = function(){</code><br />
765+<code>    DoubleIt({</code><br />
766+<code>        p:$mod,</code><br />
767+<code>        get:function(){</code><br />
768+<code>          return this.p.i</code><br />
769+<code>        },</code><br />
770+<code>        set:function(v){</code><br />
771+<code>          this.p.i=v;</code><br />
772+<code>        }</code><br />
773+<code>      });</code><br />
774+<code>  }</code><br />
775+<code>},</code><br />
776+<code>[]);</code></td>
777+</tr>
778+</tbody>
779+</table>
780+
781+Notes:
782+
783+- Contrary to Delphi/FPC it is allowed to pass a property to a var/out parameter.
784+
785+## Translating nested functions
786+
787+A nested function is translated to a local variable.
788+
789+<table>
790+<thead>
791+<tr>
792+<th>Pascal</th>
793+<th>JavaScript</th>
794+</tr>
795+</thead>
796+<tbody>
797+<tr>
798+<td><code>Unit MyModule;</code><br />
799+<code>Interface</code><br />
800+<code>Function SumNNumbers(n, Adder: integer): integer;</code><br />
801+<code>Implementation</code><br />
802+<code>Function SumNNumbers(n, Adder: integer): integer;</code><br />
803+<br />
804+<code>  Function Add(k: integer): integer;</code><br />
805+<code>  Begin</code><br />
806+<code>    if k=1 then</code><br />
807+<code>      Result:=1</code><br />
808+<code>    else</code><br />
809+<code>      Result:=Add(k-1)+Adder;</code><br />
810+<code>  End;</code><br />
811+<br />
812+<code>Begin</code><br />
813+<code>  Result:=Add(n);</code><br />
814+<code>End;</code><br />
815+<code>End.</code></td>
816+<td><code>rtl.module("MyModule",</code><br />
817+<code>["System"],</code><br />
818+<code>function(){</code><br />
819+<code>  this.DoubleIt = function(n,Adder){</code><br />
820+<code>    Result = 0;</code><br />
821+<code>    var Add = function(k) {</code><br />
822+<code>      Result = 0;</code><br />
823+<code>      if (k==1) {</code><br />
824+<code>        Result = 1;</code><br />
825+<code>      } else {</code><br />
826+<code>        Result = Add(k-1)+Adder;</code><br />
827+<code>      }</code><br />
828+<code>      return Result;</code><br />
829+<code>    };</code><br />
830+<code>    Result = Add(n);</code><br />
831+<code>    return Result;</code><br />
832+<code>  };</code><br />
833+<code>},</code><br />
834+<code>[]);</code></td>
835+</tr>
836+</tbody>
837+</table>
838+
839+Note: You can assign a nested procedure to a procedure variable. A nested procedure of a method can be assigned to a method variable.\
840+JavaScript preserves the current local scope, including references to the local variables of parent functions. Local types and constants belong to the unit scope (singleton).\
841+When a method has nested functions, the compiler adds a local var *Self*.
842+
843+## Translating for-loops
844+
845+The JavaScript for-loop executes the end expression every iteration, while Pascal only executes it once. Therefore a local variable is introduced. If the loop is not entered at all, the variable is not touched. If the loop was entered the variable contanis the last value.
846+
847+<table>
848+<thead>
849+<tr>
850+<th>Pascal</th>
851+<th>JavaScript</th>
852+</tr>
853+</thead>
854+<tbody>
855+<tr>
856+<td><code>Unit MyModule;</code><br />
857+<code>Interface</code><br />
858+<code>Function SumNNumbers(n: integer): integer;</code><br />
859+<code>Implementation</code><br />
860+<code>Function SumNNumbers(n: integer): integer;</code><br />
861+<code>Var</code><br />
862+<code>  i, j: integer;</code><br />
863+<code>Begin</code><br />
864+<code>  j:=0;</code><br />
865+<code>  For i:=1 To n Do</code><br />
866+<code>  Begin</code><br />
867+<code>    j:=j+i;</code><br />
868+<code>  End;</code><br />
869+<code>  if i&lt;1 then j:=1;</code><br />
870+<code>  Result:=j;</code><br />
871+<code>End;</code><br />
872+<code>End.</code></td>
873+<td><code>rtl.module("MyModule",</code><br />
874+<code>["System"],</code><br />
875+<code>function(){</code><br />
876+<code>  this.SumNNumbers=function(n){</code><br />
877+<code>    Result = 0;</code><br />
878+<code>    j = 0;</code><br />
879+<code>    for (var $l1 = 1, $le2 = n; $l1 &lt;= $le2; $l1++) {</code><br />
880+<code>      i = $l1;</code><br />
881+<code>      j = j + i;</code><br />
882+<code>    };</code><br />
883+<code>    if (i&lt;1) j=1;</code><br />
884+<code>    Result = j;</code><br />
885+<code>    return Result;</code><br />
886+<code>  };</code><br />
887+<code>},</code><br />
888+<code>[]);</code></td>
889+</tr>
890+</tbody>
891+</table>
892+
893+Note: The after-loop decrement is only added if *i* is read after the loop.\
894+
895+## Translating repeat..until
896+
897+The *repeat..until* is translated to a *do{}while()*.
898+
899+<table>
900+<thead>
901+<tr>
902+<th>Pascal</th>
903+<th>JavaScript</th>
904+</tr>
905+</thead>
906+<tbody>
907+<tr>
908+<td><code>Unit MyModule;</code><br />
909+<code>Interface</code><br />
910+<code>Function SumNNumbers(n: integer): integer;</code><br />
911+<code>Implementation</code><br />
912+<code>Function SumNNumbers(n: integer): integer;</code><br />
913+<code>Var</code><br />
914+<code>  i, j: integer;</code><br />
915+<code>Begin</code><br />
916+<code>  j:=0;</code><br />
917+<code>  i:=0;</code><br />
918+<code>  Repeat</code><br />
919+<code>    i:=i+1;</code><br />
920+<code>    j:=j+i;</code><br />
921+<code>  Until i&gt;=n;</code><br />
922+<code>  Result:=j;</code><br />
923+<code>End;</code><br />
924+<code>End.</code></td>
925+<td><code>rtl.module("MyModule",</code><br />
926+<code>["System"],</code><br />
927+<code>function(){</code><br />
928+<code>  this.SumNNumbers=function(n){</code><br />
929+<code>    Result = 0;</code><br />
930+<code>    j = 0;</code><br />
931+<code>    i = 0;</code><br />
932+<code>    do{</code><br />
933+<code>      i = (i + 1);</code><br />
934+<code>      j = (j + i);</code><br />
935+<code>    } while (!(i&gt;=n));</code><br />
936+<code>    Result = j;</code><br />
937+<code>    return Result;</code><br />
938+<code>  };</code><br />
939+<code>},</code><br />
940+<code>[]);</code></td>
941+</tr>
942+</tbody>
943+</table>
944+
945+## Translating while..do
946+
947+<table>
948+<thead>
949+<tr>
950+<th>Pascal</th>
951+<th>JavaScript</th>
952+</tr>
953+</thead>
954+<tbody>
955+<tr>
956+<td><code>Unit MyModule;</code><br />
957+<code>Interface</code><br />
958+<code>Function SumNNumbers(n: integer): integer;</code><br />
959+<code>Implementation</code><br />
960+<code>Function SumNNumbers(n: integer): integer;</code><br />
961+<code>Var</code><br />
962+<code>  i, j: integer;</code><br />
963+<code>Begin</code><br />
964+<code>  j:=0;</code><br />
965+<code>  i:=0;</code><br />
966+<code>  While i&lt;n Do Begin</code><br />
967+<code>    i:=i+1;</code><br />
968+<code>    j:=j+i;</code><br />
969+<code>  End;</code><br />
970+<code>  Result:=j;</code><br />
971+<code>End;</code><br />
972+<code>End.</code></td>
973+<td><code>rtl.module("MyModule",</code><br />
974+<code>["System"],</code><br />
975+<code>function(){</code><br />
976+<code>  this.SumNNumbers=function(n){</code><br />
977+<code>    var Result = 0;</code><br />
978+<code>    var j = 0;</code><br />
979+<code>    var i = 0;</code><br />
980+<code>    while(i&lt;n){</code><br />
981+<code>      i = (i + 1);</code><br />
982+<code>      j = (j + i);</code><br />
983+<code>    };</code><br />
984+<code>    Result = j;</code><br />
985+<code>    return Result;</code><br />
986+<code>  };</code><br />
987+<code>},</code><br />
988+<code>[]);</code></td>
989+</tr>
990+</tbody>
991+</table>
992+
993+## Translating case..do
994+
995+Although JavaScript has something similar in form of the "switch" statement, it lacks ranges and is on current JS engines often slower than "if-else". Therefore a case..of is translated to if..else.
996+
997+<table>
998+<thead>
999+<tr>
1000+<th>Pascal</th>
1001+<th>JavaScript</th>
1002+</tr>
1003+</thead>
1004+<tbody>
1005+<tr>
1006+<td><code>Program MyModule;</code><br />
1007+<code>Var</code><br />
1008+<code>  i: integer;</code><br />
1009+<code>Begin</code><br />
1010+<code>  case i of</code><br />
1011+<code>    1: ;</code><br />
1012+<code>    2: i:=3;</code><br />
1013+<code>  else</code><br />
1014+<code>    i:=4;</code><br />
1015+<code>  end;</code><br />
1016+<code>End.</code></td>
1017+<td><code>rtl.module("program",</code><br />
1018+<code>["System"],</code><br />
1019+<code>function(){</code><br />
1020+<code>  var $mod = this;</code><br />
1021+<code>  this.i = 0;</code><br />
1022+<code>  $mod.$main=function(n){</code><br />
1023+<code>    $tmp1 = $mod.i;</code><br />
1024+<code>    if ($tmp1 == 1){</code><br />
1025+<code>    } else if ($tmp1 == 2) {</code><br />
1026+<code>      i=3;</code><br />
1027+<code>    } else {</code><br />
1028+<code>      i=4;</code><br />
1029+<code>    }</code><br />
1030+<code>  };</code><br />
1031+<code>},</code><br />
1032+<code>[]);</code></td>
1033+</tr>
1034+</tbody>
1035+</table>
1036+
1037+## Translating with..do
1038+
1039+JavaScript has a **with**, but it is slow and deprecated. Instead a temporary variable is used:
1040+
1041+<table>
1042+<thead>
1043+<tr>
1044+<th>Pascal</th>
1045+<th>JavaScript</th>
1046+</tr>
1047+</thead>
1048+<tbody>
1049+<tr>
1050+<td><code>Unit MyModule;</code><br />
1051+<code>Interface</code><br />
1052+<code>type</code><br />
1053+<code>  TClassA = class</code><br />
1054+<code>    i: integer;</code><br />
1055+<code>  end;</code><br />
1056+<br />
1057+<code>procedure DoIt;</code><br />
1058+<br />
1059+<code>Implementation</code><br />
1060+<br />
1061+<code>procedure DoIt;</code><br />
1062+<code>begin</code><br />
1063+<code>  with TClassA.Create do</code><br />
1064+<code>    i:=3;</code><br />
1065+<code>end;</code><br />
1066+<br />
1067+<code>End.</code></td>
1068+<td><code>rtl.module("MyModule",</code><br />
1069+<code>["System"],</code><br />
1070+<code>function(){</code><br />
1071+<code>  var $mod = this;</code><br />
1072+<code>  rtl.createClass($mod, "TClassA", pas.System.TObject, function () {</code><br />
1073+<code>    this.$init = function () {</code><br />
1074+<code>      this.i = 0;</code><br />
1075+<code>    };</code><br />
1076+<code>  });</code><br />
1077+<code>  this.DoIt = function(){</code><br />
1078+<code>    var $with1 = $mod.TClassA.$create("Create");</code><br />
1079+<code>    $with1.i = 3;</code><br />
1080+<code>  };</code><br />
1081+<code>},</code><br />
1082+<code>[]);</code></td>
1083+</tr>
1084+</tbody>
1085+</table>
1086+
1087+Note: If the with-expression is already a local variable no new variable is created. This is Delphi/FPC compatible.
1088+
1089+## Translating enums
1090+
1091+Enum values are translated to numbers. The enum type is translated to an object containing a mapping from name to number and number to name.
1092+
1093+<table>
1094+<thead>
1095+<tr>
1096+<th>Pascal</th>
1097+<th>JavaScript</th>
1098+</tr>
1099+</thead>
1100+<tbody>
1101+<tr>
1102+<td><code>Unit MyModule;</code><br />
1103+<code>Interface</code><br />
1104+<code>type</code><br />
1105+<code>  TMyEnum = (</code><br />
1106+<code>    Red,</code><br />
1107+<code>    Green,</code><br />
1108+<code>    Blue);</code><br />
1109+<code>var</code><br />
1110+<code>  e: TMyEnum = Blue;</code><br />
1111+<br />
1112+<code>procedure DoIt;</code><br />
1113+<br />
1114+<code>Implementation</code><br />
1115+<br />
1116+<code>procedure DoIt;</code><br />
1117+<code>begin</code><br />
1118+<code>  e := Green;</code><br />
1119+<code>end;</code><br />
1120+<br />
1121+<code>End.</code></td>
1122+<td><code>rtl.module("MyModule",</code><br />
1123+<code>["System"],</code><br />
1124+<code>function(){</code><br />
1125+<code>  var $mod = this;</code><br />
1126+<code>  this.TMyEnum = {</code><br />
1127+<code>    "0":"Red",</code><br />
1128+<code>    Red:0,</code><br />
1129+<code>    "1":"Green",</code><br />
1130+<code>    Green:1,</code><br />
1131+<code>    "2":"Blue",</code><br />
1132+<code>    Blue:2</code><br />
1133+<code>    };</code><br />
1134+<code>  this.e = $mod.TMyEnum.Blue;</code><br />
1135+<code>  this.DoIt = function(){</code><br />
1136+<code>    $mod.e = $mod.TMyEnum.Green;</code><br />
1137+<code>  };</code><br />
1138+<code>},</code><br />
1139+<code>[]);</code></td>
1140+</tr>
1141+</tbody>
1142+</table>
1143+
1144+- Supported: ord(), low(), high(), pred(), succ(), type cast number to enum.
1145+- With optimization level -O1 the compiler uses numbers instead of names.
1146+- Not yet implemented: custom values for enum values.
1147+
1148+## Translating sets
1149+
1150+A set s is translated to a JavaScript object, where for each included enum holds *s.enumvalue==true*. This allows arbitrary large sets and the *in* operator is fast.
1151+
1152+<table>
1153+<thead>
1154+<tr>
1155+<th>Pascal</th>
1156+<th>JavaScript</th>
1157+</tr>
1158+</thead>
1159+<tbody>
1160+<tr>
1161+<td><code>Unit MyModule;</code><br />
1162+<code>Interface</code><br />
1163+<code>type</code><br />
1164+<code>  TColor = (Red, Green, Blue);</code><br />
1165+<code>  TColors = set of TColor;</code><br />
1166+<br />
1167+<code>procedure DoIt;</code><br />
1168+<br />
1169+<code>Implementation</code><br />
1170+<br />
1171+<code>procedure DoIt;</code><br />
1172+<code>var</code><br />
1173+<code>  c: TColor;</code><br />
1174+<code>  S, T: TColors;</code><br />
1175+<code>  b: boolean;</code><br />
1176+<code>begin</code><br />
1177+<code>  S:=T;</code><br />
1178+<code>  b:=Red in S;</code><br />
1179+<code>  Include(S,Blue);</code><br />
1180+<code>  Exclude(S,Blue);</code><br />
1181+<code>  S:=S+T;</code><br />
1182+<code>  S:=S-[Red,c];</code><br />
1183+<code>  b:=c in [Red..Blue];</code><br />
1184+<code>end;</code><br />
1185+<br />
1186+<code>End.</code></td>
1187+<td><code>rtl.module("MyModule",</code><br />
1188+<code>["System"],</code><br />
1189+<code>function(){</code><br />
1190+<code>  var $mod = this;</code><br />
1191+<code>  this.TColor = {</code><br />
1192+<code>    "0":"Red",</code><br />
1193+<code>    Red:0,</code><br />
1194+<code>    "1":"Green",</code><br />
1195+<code>    Green:1,</code><br />
1196+<code>    "2":"Blue",</code><br />
1197+<code>    Blue:2</code><br />
1198+<code>    };</code><br />
1199+<code>  $mod.DoIt = function(){</code><br />
1200+<code>    var c = 0;</code><br />
1201+<code>    var S = {};</code><br />
1202+<code>    var T = {};</code><br />
1203+<code>    var b = false;</code><br />
1204+<code>    S = rtl.refSet(T);</code><br />
1205+<code>    b = $mod.TColor.Red in S;</code><br />
1206+<code>    S = rtl.includeSet(S,$mod.TColor.Blue);</code><br />
1207+<code>    S = rtl.excludeSet(S,$mod.TColor.Blue);</code><br />
1208+<code>    S = rtl.unionSet(S,T);</code><br />
1209+<code>    S = rtl.diffSet(S,rtl.createSet($mod.TColor.Red,c));</code><br />
1210+<code>    b = c in rtl.createSet(null,$mod.TColor.Red,$mod.TColor.Blue);</code><br />
1211+<code>  };</code><br />
1212+<code>},</code><br />
1213+<code>[]);</code></td>
1214+</tr>
1215+</tbody>
1216+</table>
1217+
1218+- Supported:
1219+ - Include
1220+ - Exclude
1221+ - literal
1222+ - literal range, e.g. *\[EnumA..EnumB\], \['a'..'z'\]*
1223+ - union +
1224+ - difference -
1225+ - intersect *
1226+ - symmetrical difference \>\<
1227+ - equal =
1228+ - unequal \<\>
1229+ - subset \<=
1230+ - superset \>=
1231+ - set of anonymous enum type: *set of (enum1,enum2,...)*
1232+- Not supported: set of char, set of boolean
1233+- There is no optimization yet for small sets like in Delphi/FPC.
1234+- Assigning a set or passing the set as an argument only creates a reference and marks the set as *shared*. When a *shared* set is altered with Include/Exclude a new set is created (copy on write).
1235+- Passing a set as an argument might clone the set. Use the *const* modifier for parameters whenever possible.
1236+- Constant sets in expressions (e.g. *if c in \['a'..'z'\] then*) are not yet optimized and created every time. Create a *const* to avoid this.
1237+
1238+## Translating array type
1239+
1240+All arrays are translated into JavaScript arrays.\
1241+Contrary to Delphi/FPC dynamic arrays are not reference counted and do not copy on write. That means if you pass an array to a procedure and change an element, the original array is changed.
1242+
1243+<table>
1244+<thead>
1245+<tr>
1246+<th>Pascal</th>
1247+<th>JavaScript</th>
1248+</tr>
1249+</thead>
1250+<tbody>
1251+<tr>
1252+<td><code>Unit MyModule;</code><br />
1253+<code>Interface</code><br />
1254+<code>Type</code><br />
1255+<code>  TIntArr = Array of integer;</code><br />
1256+<code>  TObjArr = Array of TObject;</code><br />
1257+<code>  TRec = record c: char; end;</code><br />
1258+<code>  TRecArr = Array of TRec;</code><br />
1259+<code>Procedure Test;</code><br />
1260+<code>Implementation</code><br />
1261+<code>Procedure Test;</code><br />
1262+<code>Var</code><br />
1263+<code>  IntArr: TIntArr = (1,2,3);</code><br />
1264+<code>  ObjArr: TObjArr;</code><br />
1265+<code>  RecArr: TRecArr;</code><br />
1266+<code>Begin</code><br />
1267+<code>  IntArr:=nil;</code><br />
1268+<code>  SetLength(IntArr,4);</code><br />
1269+<code>  IntArr[2]:=2;</code><br />
1270+<code>  IntArr[1]:=length(IntArr);</code><br />
1271+<code>  SetLength(ObjArr,5);</code><br />
1272+<code>  SetLength(RecArr,2,TRec);</code><br />
1273+<code>End;</code><br />
1274+<code>End.</code></td>
1275+<td><code>rtl.module("MyModule",</code><br />
1276+<code>["System"],</code><br />
1277+<code>function(){</code><br />
1278+<code>  var $mod = this;</code><br />
1279+<code>  this.Test = function(){</code><br />
1280+<code>    this.TRec = function(s){</code><br />
1281+<code>      if (s){</code><br />
1282+<code>        this.c = s.c;</code><br />
1283+<code>      } else {</code><br />
1284+<code>        this.c = "";</code><br />
1285+<code>      };</code><br />
1286+<code>      this.$equal = function(b){</code><br />
1287+<code>        return (this.c == b.c);</code><br />
1288+<code>      };</code><br />
1289+<code>    };</code><br />
1290+<code>    this.IntArr = [1,2,3];</code><br />
1291+<code>    this.ObjArr = [];</code><br />
1292+<code>    this.RecArr = [];</code><br />
1293+<code>    this.Test = function(){</code><br />
1294+<code>      $mod.IntArr = [];</code><br />
1295+<code>      rtl.arraySetLength($mod.IntArr,4,0);</code><br />
1296+<code>      $mod.IntArr[2] = 2;</code><br />
1297+<code>      $mod.IntArr[1] = $mod.IntArr.length;</code><br />
1298+<code>      rtl.setArrayLength($mod.ObjArr,5,null);</code><br />
1299+<code>      rtl.setArrayLength($mod.RecArr,2,$mod.TRec);</code><br />
1300+<code>    }</code><br />
1301+<code>  };</code><br />
1302+<code>},</code><br />
1303+<code>[]);</code></td>
1304+</tr>
1305+</tbody>
1306+</table>
1307+
1308+Notes:
1309+
1310+- Supported features of dynamic arrays: SetLength(), Length(), equal/notequal nil, low(), high(), assigned(), concat(), copy(), insert(), delete(), multi dimensional, array of record
1311+- Dynamic array constants. E.g. in mode ObjFPC *const a: array of byte = (1,2)*. In mode Delphi you must use square brackets, *... = \[1,2\]*
1312+- Supported features of static arrays: length(), low(), high(), assigned(), concat(), copy(), const, const records
1313+- Open arrays are implemented as dynamic arrays.
1314+- Calling *Concat()* with only one array simply returns the array (no cloning). Calling it with multiple arrays creates a clone. This is Delphi 10.1 compatible.
1315+- In Delphi/FPC an empty array is *nil*. In JS it can be *null* or *\[\]*. For compatibility comparing an array with *nil* checks for *length(a)\>0*.
1316+- *function Assigned(array): boolean* results true iff *length(array)\>0*.
1317+- array of const:
1318+ - Works the same: vtInteger, vtBoolean, vtPointer, vtObject, vtClass, vtWideChar, vtInterface, vtUnicodeString
1319+ - ''longword'' is converted to ''vtNativeInt''. Delphi/FPC converts to ''vtInteger'', changing big numbers to negative numbers.
1320+ - vtExtended is double, Delphi/FPC: PExtended
1321+ - vtCurrency is currency, Delphi/FPC: PCurrency
1322+ - Not supported: vtChar, vtString, vtPChar, vtPWideChar, vtAnsiString, vtVariant, vtWideString, vtInt64, vtQWord
1323+ - only in pas2js: vtNativeInt, vtJSValue
1324+- Assignation using constant array, e.g. *a:=\[1,1,2\];*
1325+- String like operation: + operator concatenates arrays. e.g. *a:=\[1\]+\[2\];*. This is controlled by modeswitch arrayoperators, which is enabled in mode delphi.
1326+- *function copy(array,start=0,count=max): array*
1327+- *procedure insert(item,var array,const position)*
1328+- *procedure delete(var array,const start,count)*
1329+
1330+## Translating class type
1331+
1332+Classes are implemented using *Object.create* and some rtl magic.
1333+
1334+<table>
1335+<thead>
1336+<tr>
1337+<th>Pascal</th>
1338+<th>JavaScript</th>
1339+</tr>
1340+</thead>
1341+<tbody>
1342+<tr>
1343+<td><code>Unit MyModule;</code><br />
1344+<code>Interface</code><br />
1345+<code>Type</code><br />
1346+<code>  TClassA = Class(TObject)</code><br />
1347+<code>  Public</code><br />
1348+<code>    i: integer;</code><br />
1349+<code>    Procedure Add(a: integer);</code><br />
1350+<code>  End;</code><br />
1351+<code>var</code><br />
1352+<code>  ObjA: TClassA;</code><br />
1353+<code>Implementation</code><br />
1354+<code>Procedure TClassA.Add(a: integer);</code><br />
1355+<code>Begin</code><br />
1356+<code>  i:=i+a;</code><br />
1357+<code>End;</code><br />
1358+<code>Initialization</code><br />
1359+<code>  ObjA:=TClassA.Create;</code><br />
1360+<code>End.</code></td>
1361+<td><code>rtl.module("MyModule",</code><br />
1362+<code>["System"],</code><br />
1363+<code>function(){</code><br />
1364+<code>  var $mod = this;</code><br />
1365+<code>  rtl.createClass($mod,"TClassA",pas.System.TObject,function(){</code><br />
1366+<code>    this.$init = function () {</code><br />
1367+<code>      this.i = 0;</code><br />
1368+<code>    };</code><br />
1369+<code>    this.Add = function(a){</code><br />
1370+<code>      this.i = this.i + a;</code><br />
1371+<code>    };</code><br />
1372+<code>  });</code><br />
1373+<code>  this.ObjA = null;</code><br />
1374+<code>  $mod.$init = function(){</code><br />
1375+<code>    $mod.ObjA = $mod.TClassA.$create("Create");</code><br />
1376+<code>  };</code><br />
1377+<code>},</code><br />
1378+<code>[]);</code></td>
1379+</tr>
1380+</tbody>
1381+</table>
1382+
1383+Notes:
1384+
1385+- Each class and each instance is an JS object.
1386+- Each class has a globally unique JS object, created by rtl.createClass.
1387+- *Self* is never *nil*.
1388+- The method *TObject.Free* is using compiler magic. See \[#tobjectfree Translating TObject.Free\].
1389+- *Class.\$class* is a reference to the class itself.
1390+- *Class.\$ancestor* is a reference to the ancestor class.
1391+- A class has *c.\$ancestor == Object.getPrototypeOf(c)*.
1392+- A class instance has *o.\$class == Object.getPrototypeOf(o)*.
1393+- *Class.\$classname* is the short name. E.g. *TClassA.\$classname == 'TClassA*'.
1394+- *Class.\$name* is the long name. E.g. *TClassA.\$name == 'MyModule.TClassA*'.
1395+- *Class.\$unitname* is the unit name. E.g. *TClassA.\$unitname == 'MyModule*'.
1396+- The "*is*"-operator is implemented using "*isPrototypeOf*". Note that "*instanceof*" cannot be used, because classes are JS objects.
1397+- The "*as*" operator is implemented as *rtl.as(Object,Class)*.
1398+- Supported:
1399+ - constructor, destructor
1400+ - private, protected, public, strict private, strict protected
1401+ - class vars, const, nested types
1402+ - methods, class methods, class constructor, external methods
1403+ - method modifiers overload, reintroduce, virtual, override, abstract, static, external name, message integer, message string
1404+ - call inherited
1405+ - assigned()
1406+ - type cast
1407+ - class sealed, class abstract
1408+- Not supported: class destructor
1409+- Property:
1410+ - References are replaced by getter/setter.
1411+ - Supported: argument lists, default property, class property, stored modifier, index modifier.
1412+ - Not supported: getter/setter to an array element, e.g. *property A: char read FArray\[0\];*
1413+ - Class property getter/setter can be static or non static. Delphi: must be static.
1414+ - The *Index* modifier supports any constant, e.g. a string, while Delphi only allows an ordinal (longint). -2147483648 is not a special number in pas2js. Overriding a property with an index property is allowed in Delphi and pas2js.
1415+
1416+## Translating class-of type
1417+
1418+A class-of is a reference to a class. See above about translating class.
1419+
1420+<table>
1421+<thead>
1422+<tr>
1423+<th>Pascal</th>
1424+<th>JavaScript</th>
1425+</tr>
1426+</thead>
1427+<tbody>
1428+<tr>
1429+<td><code>Unit MyModule;</code><br />
1430+<code>Interface</code><br />
1431+<code>Type</code><br />
1432+<code>  TBird = Class(TObject)</code><br />
1433+<code>  Public</code><br />
1434+<code>    Class var Count: integer;</code><br />
1435+<code>    Class Procedure Add(a: integer); virtual;</code><br />
1436+<code>  End;</code><br />
1437+<code>  TBirds = class of TBird;</code><br />
1438+<br />
1439+<code>  TPigeon = Class(TBird)</code><br />
1440+<code>  Public</code><br />
1441+<code>    Class Procedure Add(a: integer); override;</code><br />
1442+<code>  End;</code><br />
1443+<br />
1444+<code>var</code><br />
1445+<code>  BirdType: TBirds;</code><br />
1446+<code>Implementation</code><br />
1447+<code>Class Procedure TBird.Add(a: integer);</code><br />
1448+<code>Begin</code><br />
1449+<code>  Count:=Count+a;</code><br />
1450+<code>End;</code><br />
1451+<code>Class Procedure TPigeon.Add(a: integer);</code><br />
1452+<code>Begin</code><br />
1453+<code>  inherited Add(a+1);</code><br />
1454+<code>End;</code><br />
1455+<code>Initialization</code><br />
1456+<code>  BirdType:=TPigeon;</code><br />
1457+<code>  BirdType.Add(1);</code><br />
1458+<code>End.</code></td>
1459+<td><code>rtl.module("MyModule",</code><br />
1460+<code>["System"],</code><br />
1461+<code>function(){</code><br />
1462+<code>  var $mod = this;</code><br />
1463+<code>  rtl.createClass($mod,"TBird",pas.System.TObject,function () {</code><br />
1464+<code>    this.Count = 0;</code><br />
1465+<code>    this.Add = function (a) {</code><br />
1466+<code>      this.Count = this.Count + a;</code><br />
1467+<code>    };</code><br />
1468+<code>  });</code><br />
1469+<code>  rtl.createClass($mod,"TPigeon",$mod.TBird,function () {</code><br />
1470+<code>    this.Add = function (a) {</code><br />
1471+<code>      $mod.TBird.Add.call(this,a + 1);</code><br />
1472+<code>    };</code><br />
1473+<code>  });</code><br />
1474+<code>  $mod.$init = function(){</code><br />
1475+<code>    $mod.BirdType = $mod.TPigeon;</code><br />
1476+<code>    $mod.BirdType.Add(1);</code><br />
1477+<code>  };</code><br />
1478+<code>},</code><br />
1479+<code>[]);</code></td>
1480+</tr>
1481+</tbody>
1482+</table>
1483+
1484+Note that *this* in a class method is the class itself.\
1485+\
1486+Notes:\
1487+
1488+- Contrary to Delphi/FPC the "is" operator works with class-of.
1489+
1490+## Translating TObject.Free
1491+
1492+In Delphi/FPC AnObject.Free checks if Self is nil, then calls the destructor and frees the memory, without changing the reference. In JavaScript however calling a method with AnObject=nil causes a crash. And memory cannot be freed explicitely. Memory is only freed if all references are gone (e.g. set to *null*).\
1493+Therefore pas2js adds code to call the destructor and sets the variable to *nil*:\
1494+
1495+- *Obj.Free* on a local variable or argument is translated to *Obj = rtl.freeLoc(Obj);*.
1496+- *Obj.Free* on a non local variable is translated to *rtl.free(this,"Obj");*.
1497+- Not supported: Freeing a property or function result.\
1498+ For example *List\[i\].Free* gives a compiler error. The property setter might create side effects, which would be incompatible to Delphi/FPC.
1499+
1500+Notes:
1501+
1502+- If the destructor raises an exception, the variable is not set to *nil*. This is compatible to Delphi/FPC, where the memory is not freed in this case.
1503+- Alternatively you can use *FreeAndNil*, which first changes the variable to *nil* and then calls the destructor.
1504+
1505+## Translating class interfaces
1506+
1507+JavaScript has nothing like it, so they are emulated.\
1508+An interfacetype is a JS-object with some hidden properties, containing the GUID (\$guid) and an array with the method names (\$names). Here is how IUnknown looks like in JS:\
1509+
1510+`{`\
1511+`  $module: [object Object],`\
1512+`  $name: "IUnknown",`\
1513+`  $fullname: "System.IUnknown",`\
1514+`  $guid: "{00000000-0000-0000-C000-000000000046}",`\
1515+`  $names: ["QueryInterface","_AddRef","_Release"],`\
1516+`  $rtti: [object Object],`\
1517+`  $kind: "com",`\
1518+`}`
1519+
1520+A class implementing interfaces has a variable *\$intfmaps*, which has for each implemented GUID a map or delegator function. A map is a JS instance of the interfacetype plus a for each method name a function to call the class method. Here is an example map of *IUnknown* of *TInterfacedObject*:\
1521+
1522+`{`\
1523+`  QueryInterface: function (){ return fn.apply(this.$o,arguments); },`\
1524+`  _AddRef: function (){ return fn.apply(this.$o,arguments); },`\
1525+`  _Release: function (){ return fn.apply(this.$o,arguments); },`\
1526+`  ...`\
1527+`}`
1528+
1529+When an interface is created for an object (here: a Pascal class instance), for example by using the *as*-operator "*ObjVar as IUnknown*", a JS object is created, which is an instance of the map object with its *\$o* set to the *ObjVar*.\
1530+\
1531+Supported:
1532+
1533+- methods, properties, default property
1534+- *{\$interfaces com\|corba\|default}*\
1535+ * COM is default, default ancestor is IUnknown (mode delphi: IInterface), managed type, i.e. automatically reference counted via _AddRef, _Release, the checks for support call QueryInterface
1536+ - CORBA: lightweight, no automatic reference counting, no default ancestor, fast support checks.
1537+- inheriting
1538+- An interface without a GUID gets one autogenerated from its name and method names.
1539+- Contrary to Delphi/FPC you can assign an interface type or var to the type TGuidString.
1540+- a class implementing an interface must not be external
1541+- a ClassType "supports" an interface, if it itself or one of its ancestors implements the interface. It does not automatically support an ancestor of the interface.
1542+- method resolution, procedure IUnknown._AddRef = IncRef;
1543+- delegation: property Name: interface\|class read Field\|Getter implements AnInterface;
1544+- is-operator:
1545+ - IntfVar is IntfType - types must be releated
1546+ - IntfVar is ClassType - types can be unrelated, class must not be external
1547+ - ObjVar is IntfType - can be unrelated
1548+- as-operator
1549+ - IntfVar as IntfType - types must be releated
1550+ - IntfVar as ClassType - types can be unrelated, nil returns nil, invalid raises EInvalidCast
1551+ - ObjVar as IntfType - can be unrelated, nil if not found, COM: uses _AddRef
1552+- typecast:
1553+ - IntfType(IntfVar) - must be related
1554+ - ClassType(IntfVar) - can be unrelated, nil if invalid
1555+ - IntfType(ObjVar) - nil if not found, COM: if ObjVar has delegate uses _AddRef
1556+ - TJSObject(IntfTypeOrVar). Note that you cannot typecast directly to a *TJSObject* descendant. You can use *TJSWindow(TJSObject(IntfType))*.
1557+ - jsvalue(intfvar)
1558+- Assign operator:
1559+ - IntfVar:=nil;
1560+ - IntfVar:=IntfVar2; - IntfVar2 must be same type or a descendant
1561+ - IntfVar:=ObjVar; - nil if unsupported
1562+ - jsvalue:=IntfVar;
1563+ - TGUIDVar:=IntfType;
1564+ - TGUIDVar:=IntfVar;
1565+ - TGUIDVar:=stringconstant;
1566+ - TGUIDStringVar:=IntfVar;
1567+ - StringVar:=GuidVar;
1568+- Equal/Inequal operator:
1569+ - IntfVar=nil;
1570+ - IntfVar=IntfVar2; - must be related
1571+ - jsvalue=IntfVar;
1572+ - TGUIDVar=IntfType;
1573+ - TGUIDVar=IntfVar;
1574+ - TGUIDVar=string;
1575+ - TGUIDStringVar=IntfVar;
1576+- Passing an COMIntfVar to an untyped parameter or *JSValue* does not trigger *_AddRef, _Release*.
1577+- Assigned(IntfVar)
1578+- RTTI, typeinfo(IntfType), typeinfo(IntfVar)
1579+
1580+Not yet supported: array of intferfacetype, interface as record member.
1581+
1582+## Translating helpers
1583+
1584+Pas2js supports class helpers, record helpers and type helpers since 1.3. The extend is only virtual, the helped type is kept untouched.\
1585+
1586+- A **class helper** can "extend" Pascal classes and external JS classes.
1587+- A **record helper** can "extend" a record type. In \$mode delphi a record helper can extend other types as well, see *type helper*
1588+- A **type helper** can extend all base types like integer, string, char, boolean, double, currency, and user types like enumeration, set, range, array, class, record and interface types. It cannot extend helpers and procedural types.\
1589+ Type helpers are enabled by default in *\$mode delphi* and disabled in *\$mode objfpc*. You can enable them with **{\$modeswitch typehelpers}**.
1590+- By default only one helper is active per type, same as in FPC/Delphi. If there are multiple helpers for the same type, the last helper in scope wins.\
1591+ A class with ancestors can have one active helper per ancestor type, so multiple helpers can be active, same as FPC/Delphi.\
1592+ Using **{\$modeswitch multihelpers}** you can activate all helpers within scope.
1593+- Nested helpers (e.g. *TDemo.TSub.THelper*) are elevated. Visibility is ignored. Same as FPC/Delphi.
1594+- Helpers cannot be forward defined (e.g. no *THelper = helper;*).
1595+- Helpers must not have fields.
1596+- **Class Var, Const, Type**
1597+- **Visibility** : *strict private .. published*
1598+- **Function, procedure**: In class and record helpers *Self* is the class/record instance. For other types Self is a reference to the passed value.
1599+- **Class function, class procedure**: Helpers for Pascal classes/records can add *static* and non static class functions. Helpers for external classes and other types can only add static class functions.
1600+- **Constructor**. Not for external classes. Works similar to construcors, i.e. *THelpedClass.Create* creates a new instance, while *AnObj.Create* calls the constructor function as normal method. Note that Delphi does not allow calling helper construcors as normal method.
1601+- no destructor
1602+- **Property** : getters/setters can refer to members of the helper, its ancestors and the helped class/record.
1603+- **Class property** : getter can be static or non static. Delphi/FPC only allows static.
1604+- **Ancestors** : Helpers can have an ancestor helper, but they do not have a shared root class, especially not *TObject*.
1605+- **no virtual, abstract, override**. Delphi allows them, but 10.3 crashes when calling.
1606+- **inherited** : *inherited* inside a method of a class/record calls helper of ancestor.\
1607+ *inherited* inside a helper depends on the \$mode:
1608+ - *\$mode objfpc* : *inherited;* and *inherited Name(args);* work the same and searches first in HelperForType, then in ancestor(s).
1609+ - *\$mode delphi: inherited;* : skip ancestors and HelperForType, searches first in helper(s) of ancestor of HelperForType.
1610+ - *\$mode delphi: inherited name(args);* : same as \$mode objfpc first searches in HelperForType, then Ancestor(s) In any case if *inherited;* has no ancestor to call, it is silently ignored, while *inherited Name;* gives an error.
1611+- **RTTI**: *typeinfo(somehelper)* returns a pointer to *TTypeInfoHelper* with *Kind tkHelper*.
1612+- There are some special cases when using a **type helper** function/procedure on a value:
1613+ - *function result* : using a temporary variable
1614+ - *const, const argument* : When helper function tries to assign a value, pas2js raises a EPropReadOnly exception. FPC/Delphi use a temporary variable allowing the write.
1615+ - *property* : uses only the getter, ignoring the setter. This breaks OOP, as it allows to change fields without calling the setter. This is FPC/Delphi compatible.
1616+ - *with value do ;* : uses a temporary variable. Delphi/FPC do not support it.
1617+- A method with *external name* modifier is treated as an external method of the helped type.
1618+
1619+## Translating attributes
1620+
1621+Attributes are stored in the TTypeInfo objects as streams stored in an array. See the function *GetRTTIAttributes* in unit *TypInfo* for details.
1622+
1623+## Translating try..finally
1624+
1625+JavaScript has the same, so it translates straight forward.
1626+
1627+## Translating try..except
1628+
1629+<table>
1630+<thead>
1631+<tr>
1632+<th>Pascal</th>
1633+<th>JavaScript</th>
1634+</tr>
1635+</thead>
1636+<tbody>
1637+<tr>
1638+<td><code>Unit MyModule;</code><br />
1639+<code>Interface</code><br />
1640+<code>Uses SysUtils, Math, JS;</code><br />
1641+<code>Function DoIt(n: integer): double;</code><br />
1642+<code>Implementation</code><br />
1643+<code>Function DoIt(n: integer): double;</code><br />
1644+<code>var E: Exception;</code><br />
1645+<code>Begin</code><br />
1646+<code>  try</code><br />
1647+<code>    Result:=double(7.0)/n;</code><br />
1648+<code>    if not IsFinite(Result) then</code><br />
1649+<code>      if n=0 then</code><br />
1650+<code>        raise EZeroDivide.Create</code><br />
1651+<code>      else</code><br />
1652+<code>        raise EOverflow.Create;</code><br />
1653+<code>  except</code><br />
1654+<code>    on EZeroDivide do Result:=0.0;</code><br />
1655+<code>    on E2: EOverflow do Result:=0.0;</code><br />
1656+<code>    else</code><br />
1657+<code>      raise EAbort.Create('Something other: '+String(JS.JSExceptObject));</code><br />
1658+<code>  end;</code><br />
1659+<code>End;</code><br />
1660+<code>End.</code></td>
1661+<td><code>rtl.module("MyModule",</code><br />
1662+<code>["System","SysUtils"],</code><br />
1663+<code>function(){</code><br />
1664+<code>  this.DoIt=function(n){</code><br />
1665+<code>    Result = 0;</code><br />
1666+<code>    var E = null;</code><br />
1667+<code>    try{</code><br />
1668+<code>      Result = 7.0 / n;</code><br />
1669+<code>      if (!IsFinite(Result)){</code><br />
1670+<code>        if (n==0){</code><br />
1671+<code>          throw pas.SysUtils.EZeroDivide.$create("Create");</code><br />
1672+<code>        } else {</code><br />
1673+<code>          throw pas.SysUtils.EOverflow.$create("Create");</code><br />
1674+<code>        };</code><br />
1675+<code>      };</code><br />
1676+<code>    }catch($e){</code><br />
1677+<code>      if (pas.SysUtils.EZeroDivide.isPrototypeOf($e)){</code><br />
1678+<code>        Result = 0.0;</code><br />
1679+<code>      } else if (pas.SysUtils.EOverflow.isPrototypeOf($e)){</code><br />
1680+<code>        var E2 = $e;</code><br />
1681+<code>        Result = 0.0;</code><br />
1682+<code>      } else {</code><br />
1683+<code>        throw pas.SysUtils.EAbort.$create("Create",["Something other: "+(""+$e)]);</code><br />
1684+<code>      }</code><br />
1685+<code>    }</code><br />
1686+<code>    return Result;</code><br />
1687+<code>  };</code><br />
1688+<code>},</code><br />
1689+<code>[]);</code></td>
1690+</tr>
1691+</tbody>
1692+</table>
1693+
1694+Notes:
1695+
1696+- Division by zero does not raise an exception in JavaScript. Instead it results in Infinity, except for 0/0 which results in NaN.
1697+- There is no ExceptObject in SysUtils.
1698+- When calling external functions keep in mind that JS allows to throw (raise) any value, often a string.\
1699+ You can access the current except value via JSExceptValue in unit JS.\
1700+ Note that this is only valid inside the catch-block. The compiler will not warn, if you use it outside.
1701+
1702+## Translating enumerators
1703+
1704+The for..in..do supports enumerating:
1705+
1706+- ordinal types like char, boolean, byte, ..., longword, enums, custom ranges are translated to a for loop.
1707+- set types are translated to a for loop, while const sets and set variables are enumerated via a for(...in...) loop.
1708+- string and array variables are enumerated via for loops.
1709+- for aString in ArrayOfString do ...
1710+- *for key in jsvalue do* translates to *for (key in jsvalue){}*
1711+- *for key in ExternalClass do*\
1712+ * If the externalclass has a ''length'' and a matching default property it uses the enumeration of an array. For example *for value in TJSArray do* enumerates the values of the array, not the index. It checks if the array is nil.
1713+ - Otherwise it translates to *for (key in externalclass){}*, which enumerates the keys (property names) of the JS object.
1714+
1715+The class GetEnumerator function is translated like this:
1716+
1717+<table>
1718+<thead>
1719+<tr>
1720+<th>Pascal</th>
1721+<th>JavaScript</th>
1722+</tr>
1723+</thead>
1724+<tbody>
1725+<tr>
1726+<td><code>Unit MyModule;</code><br />
1727+<code>Interface</code><br />
1728+<br />
1729+<code>uses Classes;</code><br />
1730+<br />
1731+<code>procedure DoIt(List: TList);</code><br />
1732+<br />
1733+<code>Implementation</code><br />
1734+<br />
1735+<code>procedure DoIt(List: TList);</code><br />
1736+<code>var</code><br />
1737+<code>  Item: Pointer;</code><br />
1738+<code>begin</code><br />
1739+<code>  for Item in List do</code><br />
1740+<code>    if Item&lt;&gt;nil then ;</code><br />
1741+<code>end;</code><br />
1742+<br />
1743+<code>End.</code></td>
1744+<td><code>rtl.module("MyModule",</code><br />
1745+<code>["System","Classes"],</code><br />
1746+<code>function(){</code><br />
1747+<code>  this.DoIt=function(List){</code><br />
1748+<code>    var Item = null;</code><br />
1749+<code>    var $in1 = List;</code><br />
1750+<code>    try {</code><br />
1751+<code>      while ($in1.MoveNext()) {</code><br />
1752+<code>        Item = $in1.GetCurrent();</code><br />
1753+<code>        if (Item !== null) ;</code><br />
1754+<code>      }</code><br />
1755+<code>    } finally {</code><br />
1756+<code>      $in1 = rtl.freeLoc($in1)</code><br />
1757+<code>    };</code><br />
1758+<code>  };</code><br />
1759+<code>},</code><br />
1760+<code>[]);</code></td>
1761+</tr>
1762+</tbody>
1763+</table>
1764+
1765+Notes:
1766+
1767+- Not supported: operator Enumerator, member modifier enumerator (i.e. custom Current and MoveNext)
1768+
1769+## Translating function types
1770+
1771+JavaScript functions work like Delphi's "reference to function", which means like closures, capturing outer variables. Assigning a normal function or nested function to a procedural variable is translated to a simple assignment. A Pascal method needs **this** to be the class or class instance.\
1772+Note that *bind* cannot be used, because it does not support the *equal* operator. Instead a wrapper is created:
1773+
1774+<table>
1775+<thead>
1776+<tr>
1777+<th>Pascal</th>
1778+<th>JavaScript</th>
1779+</tr>
1780+</thead>
1781+<tbody>
1782+<tr>
1783+<td><code>Program MyModule;</code><br />
1784+<code>type</code><br />
1785+<code>  TMyMethod = procedure(n: integer) of object;</code><br />
1786+<code>  TBird = class</code><br />
1787+<code>    procedure DoIt(n: integer); virtual; abstract;</code><br />
1788+<code>  end;</code><br />
1789+<code>  TMyProc = procedure(n: integer);</code><br />
1790+<code>procedure DoSome(n: integer);</code><br />
1791+<code>begin</code><br />
1792+<code>end;</code><br />
1793+<code>var</code><br />
1794+<code>  m: TMyMethod;</code><br />
1795+<code>  Bird: TBird;</code><br />
1796+<code>  p: TMyProc;</code><br />
1797+<code>Begin</code><br />
1798+<code>  m:=@Bird.DoIt;</code><br />
1799+<code>  m(3);</code><br />
1800+<code>  p:=@DoSome;</code><br />
1801+<code>  p(4);</code><br />
1802+<code>End.</code></td>
1803+<td><code>rtl.module("program",</code><br />
1804+<code>["System","UnitA"],</code><br />
1805+<code>function(){</code><br />
1806+<code>  var $mod = this;</code><br />
1807+<code>  rtl.createClass($mod,"TBird",pas.System.TObject,function(){</code><br />
1808+<code>    this.DoIt = function (n) {</code><br />
1809+<code>    };</code><br />
1810+<code>  });</code><br />
1811+<code>  this.DoSome = function (n) {</code><br />
1812+<code>  };</code><br />
1813+<code>  this.m = null;</code><br />
1814+<code>  this.Bird = null;</code><br />
1815+<code>  this.p = null;</code><br />
1816+<code>  $mod.$main = function() {</code><br />
1817+<code>    $mod.m = rtl.createCallback($mod.Bird,"DoIt");</code><br />
1818+<code>    $mod.m(3);</code><br />
1819+<code>    $mod.p = $mod.DoSome;</code><br />
1820+<code>    $mod.p(4);</code><br />
1821+<code>  };</code><br />
1822+<code>},</code><br />
1823+<code>[]);</code><br />
1824+<br />
1825+<code>rtl = {</code><br />
1826+<code>  ...</code><br />
1827+<code>  createCallback: function(scope, fn){</code><br />
1828+<code>    var cb;</code><br />
1829+<code>    if (typeof(fn)==='string'){</code><br />
1830+<code>      cb = function(){</code><br />
1831+<code>        return scope[fn].apply(scope,arguments);</code><br />
1832+<code>      };</code><br />
1833+<code>    } else {</code><br />
1834+<code>      cb = function(){</code><br />
1835+<code>        return fn.apply(scope,arguments);</code><br />
1836+<code>      };</code><br />
1837+<code>    };</code><br />
1838+<code>    cb.scope = scope;</code><br />
1839+<code>    cb.fn = fn;</code><br />
1840+<code>    return cb;</code><br />
1841+<code>  },</code><br />
1842+<code>  ...</code></td>
1843+</tr>
1844+</tbody>
1845+</table>
1846+
1847+Notes:
1848+
1849+- You can assign a nested procedure to procedure variable. You don't need and you must not add the FPC "*is nested*" modifier.
1850+- In pas2js a procedural typed declared as **reference to** accepts procedures, local procedures and methods. Delphi only supports capturing procedures and methods. FPC 3.0.4 does not support reference-to.
1851+- In pas2js the calling convention *safecall* has a special meaning:\
1852+ Assigning a procedure/method, uses *rtl.createSafeCallback* instead of *createCallback*, enclosing a call in a *try..catch* block. When an exception is thrown by JS, it is caught and delegated to *rtl.handleUncaughtException(err)*.\
1853+ For example:\
1854+ *aButtonElement.OnClick:=@DoClick;* uses *rtl.createSafeCallback*\
1855+ *aButtonElement.OnClick:=SomeElement.OnClick;* does not.\
1856+
1857+## Translating anonymous functions
1858+
1859+Anonymous functions are supported since pas2js 1.1.\
1860+Note that in pas2js local procedures are closures as well. See below.\
1861+For pas2js 1.0 the next best thing are local procedures. For example:
1862+
1863+<table>
1864+<thead>
1865+<tr>
1866+<th>Delphi</th>
1867+<th>Pas2js</th>
1868+</tr>
1869+</thead>
1870+<tbody>
1871+<tr>
1872+<td><code>Program MyModule;</code><br />
1873+<code>type</code><br />
1874+<code>  TAdder = reference to function(n: integer): integer;</code><br />
1875+<br />
1876+<code>function CreateAdder(a: integer): TAdder;</code><br />
1877+<code>begin</code><br />
1878+<code>  Result:=function(b: integer)</code><br />
1879+<code>    begin</code><br />
1880+<code>      Result:=a+b;</code><br />
1881+<code>    end;</code><br />
1882+<code>end;</code><br />
1883+<br />
1884+<code>var</code><br />
1885+<code>  Adder: TAdder;</code><br />
1886+<code>Begin</code><br />
1887+<code>  Adder:=CreateAdder(3);</code><br />
1888+<code>  writeln(Adder(5)); // gives 8</code><br />
1889+<code>End.</code></td>
1890+<td><code>Program MyModule;</code><br />
1891+<code>type</code><br />
1892+<code>  TAdder = reference to function(n: integer): integer;</code><br />
1893+<br />
1894+<code>function CreateAdder(a: integer): TAdder;</code><br />
1895+<code>  function Add(b: integer): integer;</code><br />
1896+<code>  begin</code><br />
1897+<code>    Result:=a+b;</code><br />
1898+<code>  end;</code><br />
1899+<code>begin</code><br />
1900+<code>  Result:=@Add;</code><br />
1901+<code>end;</code><br />
1902+<br />
1903+<code>var</code><br />
1904+<code>  Adder: TAdder;</code><br />
1905+<code>Begin</code><br />
1906+<code>  Adder:=CreateAdder(3);</code><br />
1907+<code>  writeln(Adder(5)); // gives 8</code><br />
1908+<code>End.</code></td>
1909+</tr>
1910+</tbody>
1911+</table>
1912+
1913+## Translating var modifier absolute
1914+
1915+The absolute modifier works as an alias. That means it works FPC/Delphi compatible for related types like Pointer and TObject, and works incompatible for unrelated types like longword and record (e.g. *var r: TPoint absolute MyLongInt*).\
1916+The modifier is currently only supported for local variables.
1917+
1918+## Translating assert()
1919+
1920+The Assert(boolean\[,string\]) function is translated to *if(bool) throw x*. If unit sysutils is used, it creates an EAssertFailed exception.\
1921+Otherwise it throws a string.\
1922+
1923+- Command line enable with -Sa, disable with -Sa-
1924+- In code enable with *{\$C+}* or *{\$Assertions on}*, disable with *{\$C-}* or *{\$Assertions off}*
1925+
1926+## Dispatch messages
1927+
1928+The procedure modifier **message** and the **Dispatch** method works similar to FPC/Delphi, as it expects a record of a specific format and ***TObject.Dispatch*** calls the corresponding method with that message number or string.\
1929+The procedure modifier *message \<integer\>* adds an entry to hidden *YourClass.\$msgint* object, while the modifier *message \<string\>* adds an entry to the hidden *YourClass.\$msgstr* object.\
1930+Two new directives ***{\$DispatchField fieldname}**'' and***{\$DispatchStrField fieldname}**'' were added. Insert these directives in front of your class declaration to let the compiler check all methods with message modifiers of this class and its descendants whether they pass a record with the required field. For example:
1931+
1932+`  {$DispatchField Msg} // enable checking message methods for record field name "Msg"`\
1933+`  {$DispatchStrField MsgStr}`\
1934+`  TObject = class`\
1935+`    procedure Dispatch(var aMessage); virtual;`\
1936+`    procedure DispatchStr(var aMessage); virtual;`\
1937+`  end;`\
1938+`  TMouseDownMsg = record`\
1939+`    Id: integer; // Id instead of Msg, works in FPC, but not in pas2js`\
1940+`    x,y: integer;`\
1941+`  end;`\
1942+`  TMouseUpMsg = record`\
1943+`    MsgStr: string;`\
1944+`    X,Y: integer;`\
1945+`  end;`\
1946+`  TWinControl = class`\
1947+`    procedure MouseDownMsg(var Msg: TMouseDownMsg); message 3; // warning: Dispatch requires record field Msg`\
1948+`    procedure MouseUpMsg(var Msg: TMouseUpMsg); message 'up'; // ok, record with string field name MsgStr`\
1949+`  end;`
1950+
1951+Note that descendant classes can override the *\$DispatchField* or disable the check using *{\$DispatchField -}*.
1952+
1953+## Calling JavaScript from Pascal
1954+
1955+Pas2js allows to write low level functions and/or access a JavaScript library with the following possibilities:
1956+
1957+## The asm block
1958+
1959+The asm block is pure JavaScript, that is copied directly into the generated .js file.
1960+
1961+<table>
1962+<thead>
1963+<tr>
1964+<th>Pascal</th>
1965+<th>JavaScript</th>
1966+</tr>
1967+</thead>
1968+<tbody>
1969+<tr>
1970+<td><code>Program MyModule;</code><br />
1971+<code>var</code><br />
1972+<code>  s: string;</code><br />
1973+<code>Begin</code><br />
1974+<code>  s = 'Hello World!';</code><br />
1975+<code>  Asm</code><br />
1976+<code>    console.log(s);</code><br />
1977+<code>  End;</code><br />
1978+<code>End.</code></td>
1979+<td><code>rtl.module("program",</code><br />
1980+<code> ["System"],</code><br />
1981+<code> function(){</code><br />
1982+<code>   var $mod = this;</code><br />
1983+<code>   this.s = '';</code><br />
1984+<code>   $mod.$main = function(){</code><br />
1985+<code>     $mod.s = "Hello World!";</code><br />
1986+<code>     console.log(s);</code><br />
1987+<code>   };</code><br />
1988+<code> },</code><br />
1989+<code> []);</code><br />
1990+<code> </code></td>
1991+</tr>
1992+</tbody>
1993+</table>
1994+
1995+Notes:
1996+
1997+- The block is indented to produce more readable JS code. All lines are indented or unindented the same amount, i.e. sub indentation is kept.
1998+- The compiler does neither parse, nor check the syntax of the JS.
1999+- The compiler does not know what Pascal identifiers are used by the asm-block and might remove them, if no Pascal code is using them. To make sure that an identifier is kept, add some dummy code like *if MyVar=0 then;*
2000+- Accessing an interface, program or library identifier:\
2001+ * From inside the module you can use *\$mod.Identifier*.
2002+ - Otherwise use the fully qualified path *pas.Unitname.Identifier*.
2003+- Accessing an implementation identifier:\
2004+ * From inside the unit you can use *\$impl.Identifier*.
2005+ - Otherwise use the path *pas.Unitname.\$impl.Identifier*.
2006+- Accessing a class instance member (field, procedure, function, constructor, destructor) from a method of the class: use *this.Identifier*. Inside a nested function of a method you use the *Self.Identifier*.
2007+- Accessing a class member (class var, class procedure, class function) from a method of the class: for writing use *this.\$class.Identifier*, for reading you can omit the *\$class*.
2008+- Accessing a class member (class var, class procedure, class function) from a class method of the class: use *this.Identifier*.
2009+- Access to Properties must use the getter/setter.
2010+- When calling a Pascal method, make sure the **this** is correct:
2011+ - A class method (e.g. *class function*, *class procedure*) needs the class as *this*.\
2012+ **Wrong**: *aCar.DoIt(params,...)*\
2013+ **Correct**: *aCar.\$class.DoIt(params,...)*\
2014+- Calling a Pascal function from a HTML/DOM-element: For example to call a function when user clicks a DOM element you can assign a function to the *onclick* property. This will call the function with *this* set to the DOM element.\
2015+ Pascal methods needs a wrapper to set *this* to the instance. Examples:
2016+ - An unit function: *DOMElement.onclick = \$mod.DoIt;*
2017+ - An implementation function: *DOMElement.onclick = \$impl.DoIt;*.
2018+ - A method: *DOMElement.onclick = this.DoIt.bind(this);*
2019+ - A class function/procedure: *DOMElement.onclick = this.DoIt.bind(this.\$class);*
2020+ - A nested function: *DOMElement.onclick = DoIt;*.
2021+
2022+## The procedure modifier assembler
2023+
2024+You can write pure JavaScript functions like this:
2025+
2026+<table>
2027+<thead>
2028+<tr>
2029+<th>Pascal</th>
2030+<th>JavaScript</th>
2031+</tr>
2032+</thead>
2033+<tbody>
2034+<tr>
2035+<td><code>Program MyModule;</code><br />
2036+<br />
2037+<code>Procedure Log(const s: string); assembler;</code><br />
2038+<code>Asm</code><br />
2039+<code>  console.log(s);</code><br />
2040+<code>end;</code><br />
2041+<br />
2042+<code>Begin</code><br />
2043+<code>  Log('Hello World!');</code><br />
2044+<code>End.</code></td>
2045+<td><code>rtl.module("program",</code><br />
2046+<code>["System"],</code><br />
2047+<code>function(){</code><br />
2048+<code>  var $mod = this;</code><br />
2049+<code>  this.Log = function(s){</code><br />
2050+<code>    console.log(s);</code><br />
2051+<code>  };</code><br />
2052+<code>  $mod.$main = function(){</code><br />
2053+<code>    $mod.Log("Hello World!");</code><br />
2054+<code>  };</code><br />
2055+<code>},</code><br />
2056+<code>[]);</code></td>
2057+</tr>
2058+</tbody>
2059+</table>
2060+
2061+See also \[#asm asm\].
2062+
2063+## The procedure modifier external
2064+
2065+The procedure modifier *external* requires a string constant and tells the compiler to replace a reference with this string value. The value is not checked for JS syntax.
2066+
2067+<table>
2068+<thead>
2069+<tr>
2070+<th>Pascal</th>
2071+<th>JavaScript</th>
2072+</tr>
2073+</thead>
2074+<tbody>
2075+<tr>
2076+<td><code>Program MyModule;</code><br />
2077+<code>Procedure ConsoleLog(const s: string); external name 'console.log';</code><br />
2078+<code>// Note: an external procedure has no begin..end block</code><br />
2079+<code>Begin</code><br />
2080+<code>  ConsoleLog('Hello World!');</code><br />
2081+<code>End.</code></td>
2082+<td><code>rtl.module("program",</code><br />
2083+<code>["System"],</code><br />
2084+<code>function(){</code><br />
2085+<code>  var $mod = this;</code><br />
2086+<code>  $mod.$main = function(){</code><br />
2087+<code>    console.log("Hello World!");</code><br />
2088+<code>  };</code><br />
2089+<code>},</code><br />
2090+<code>[]);</code></td>
2091+</tr>
2092+</tbody>
2093+</table>
2094+
2095+## The procedure modifier varargs
2096+
2097+Appending the **varargs** modifier to a procedure allows to pass arbitrary more parameters to a function. By default these parameters are untyped, i.e. any type fits. Alternatively you can use **varargs of aType** to allow only specific types.\
2098+To access these arguments use either *JSArguments* from unit JS or an *asm..end* block.
2099+
2100+<table>
2101+<thead>
2102+<tr>
2103+<th>Pascal</th>
2104+<th>JavaScript</th>
2105+</tr>
2106+</thead>
2107+<tbody>
2108+<tr>
2109+<td><code>Program MyModule;</code><br />
2110+<code>uses JS;</code><br />
2111+<code>function Sum(b: boolean): longint; varargs;</code><br />
2112+<code>var i: longint;</code><br />
2113+<code>begin</code><br />
2114+<code>  if b then</code><br />
2115+<code>    asm</code><br />
2116+<code>      for (var i=0; i&lt;arguments.length; i++) Result+=arguments[i];</code><br />
2117+<code>    end</code><br />
2118+<code>  else</code><br />
2119+<code>    for i:=0 to JSArguments.length-1 do</code><br />
2120+<code>      Result:=Result+longint(JSArguments[i]);</code><br />
2121+<code>end;</code><br />
2122+<code>var</code><br />
2123+<code>  i: integer;</code><br />
2124+<code>Begin</code><br />
2125+<code>  i:=Sum(true,2,4,6); // i=12</code><br />
2126+<code>  i:=Sum(false,2,4,6); // i=12</code><br />
2127+<code>End.</code></td>
2128+<td><code>rtl.module("program",</code><br />
2129+<code>["System","JS"],</code><br />
2130+<code>function(){</code><br />
2131+<code>  var $mod = this;</code><br />
2132+<code>  this.Sum = function(b){</code><br />
2133+<code>    var Result = 0;</code><br />
2134+<code>    var i = 0;</code><br />
2135+<code>    if (b){</code><br />
2136+<code>      for (var i=0; i&lt;arguments.length; i++) Result+=arguments[i];</code><br />
2137+<code>    } else {</code><br />
2138+<code>      for (var $l1 = 1, $le2 = argumens.length; $l1 &lt;= $le2; $l1++){</code><br />
2139+<code>        $i = $l1;</code><br />
2140+<code>        Result = Result + arguments[i];</code><br />
2141+<code>      }</code><br />
2142+<code>    }</code><br />
2143+<code>    return Result;</code><br />
2144+<code>  };</code><br />
2145+<code>  this.i = 0;</code><br />
2146+<code>  $mod.$main = function(){</code><br />
2147+<code>    $mod.i = $mod.Sum(true,2,4,6);</code><br />
2148+<code>    $mod.i = $mod.Sum(false,2,4,6);</code><br />
2149+<code>  };</code><br />
2150+<code>},</code><br />
2151+<code>[]);</code></td>
2152+</tr>
2153+</tbody>
2154+</table>
2155+
2156+The above example defines a function *Sum*, that requires the first parameter to be a boolean and then an arbitrary number of parameters. The compiler does not type check the other parameters, so you can pass anything readable.
2157+
2158+## The var modifier external
2159+
2160+The var modifier *external* allows to use a JavaScript variable or constant.
2161+
2162+<table>
2163+<thead>
2164+<tr>
2165+<th>Pascal</th>
2166+<th>JavaScript</th>
2167+</tr>
2168+</thead>
2169+<tbody>
2170+<tr>
2171+<td><code>Program MyModule;</code><br />
2172+<code>var</code><br />
2173+<code>  EulersNumber: Double; external name 'Math.E';</code><br />
2174+<code>  d: double;</code><br />
2175+<code>Begin</code><br />
2176+<code>  d:=EulersNumber;</code><br />
2177+<code>End.</code></td>
2178+<td><code>rtl.module("program",</code><br />
2179+<code>["System"],</code><br />
2180+<code>function(){</code><br />
2181+<code>  var $mod = this;</code><br />
2182+<code>  this.d = 0.0;</code><br />
2183+<code>  $mod.$main = function(){</code><br />
2184+<code>    $mod.d = Math.E;</code><br />
2185+<code>  };</code><br />
2186+<code>},</code><br />
2187+<code>[]);</code></td>
2188+</tr>
2189+</tbody>
2190+</table>
2191+
2192+## The external modifier of class members
2193+
2194+The method modifier *external* works as the procedure modifier, except it uses the scope of the class or instance.\
2195+The field modifier *external* works as the var modifier, except it uses the scope of the class or instance.\
2196+Requires the modeswitch **externalclass**.
2197+
2198+<table>
2199+<thead>
2200+<tr>
2201+<th>Pascal</th>
2202+<th>JavaScript</th>
2203+</tr>
2204+</thead>
2205+<tbody>
2206+<tr>
2207+<td><code>Program MyModule;</code><br />
2208+<code>{$modeswitch externalclass}</code><br />
2209+<code>type</code><br />
2210+<code>  TWrapper = class</code><br />
2211+<code>  private</code><br />
2212+<code>    // let's assume this object has the properties "$Handle", "$id", and "0"</code><br />
2213+<code>  public</code><br />
2214+<code>    Id: NativeInt; external name '$Id';</code><br />
2215+<code>    x: NativeInt; external name '[0]';</code><br />
2216+<code>    y: NativeInt; external name '["A B"]';</code><br />
2217+<code>    function GetState(typ: longint): NativeInt; external name '$Handle.GetState';</code><br />
2218+<code>    procedure DoIt;</code><br />
2219+<code>  end;</code><br />
2220+<code>procedure TWrapper.DoIt;</code><br />
2221+<code>begin</code><br />
2222+<code>  Id := GetState(4);</code><br />
2223+<code>end;</code><br />
2224+<code>var</code><br />
2225+<code>  W: TWrapper;</code><br />
2226+<code>Begin</code><br />
2227+<code>  W.Id := 2;</code><br />
2228+<code>  W.x := 3;</code><br />
2229+<code>  W.y := 4;</code><br />
2230+<code>  W.GetState(5);</code><br />
2231+<code>End.</code></td>
2232+<td><code>rtl.module("program",</code><br />
2233+<code>["System"],</code><br />
2234+<code>function(){</code><br />
2235+<code>  var $mod = this;</code><br />
2236+<code>  rtl.createClass($mod, "TWrapper", pas.System.TObject, function () {</code><br />
2237+<code>    this.DoIt = function(){</code><br />
2238+<code>      this.$Id = this.$Handle.GetState(4);</code><br />
2239+<code>    };</code><br />
2240+<code>  });</code><br />
2241+<code>  this.W = null;</code><br />
2242+<code>  $mod.$main = function(){</code><br />
2243+<code>    $mod.W.$Id = 2;</code><br />
2244+<code>    $mod.W[0] = 3;</code><br />
2245+<code>    $mod.W["A B"] = 4;</code><br />
2246+<code>    $mod.W.$Handle.GetState(5);</code><br />
2247+<code>  };</code><br />
2248+<code>},</code><br />
2249+<code>[]);</code></td>
2250+</tr>
2251+</tbody>
2252+</table>
2253+
2254+- Non identifiers like "0" or "A B" must be enclosed in brackets.
2255+
2256+## External classes
2257+
2258+pas2js introduces a new class modifier "*external name*", which makes the whole class external. External classes allow to easily declare Pascal wrappers for JavaScript objects and function objects.\
2259+They need the modeswitch **externalclass** in front of the class.\
2260+An external class is not a TObject and has none of its methods.\
2261+All members are external. If you omit the *external* modifier the external name is the member name. Keep in mind that JS is case sensitive.\
2262+Properties work the same as with Pascal classes, i.e. are replaced by Getter/Setter.\
2263+Destructors are not allowed.\
2264+Constructors are supported in four ways:
2265+
2266+- *constructor New* is translated to *new ExtClass(params)*, and for nested external class: *new ExtParentClass.ExtClass(Params)*
2267+- *constructor New; external name ''GlobalFunc''* is translated to *new GlobalFunc(params)*.
2268+- *constructor SomeName; external name*'{}' is translated to *{}*.
2269+- Otherwise it is translated to *new ExtClass.FuncName(params)*, and for nested external class: *new ExtParentClass.ExtClass.FuncName(params)*.
2270+
2271+<table>
2272+<thead>
2273+<tr>
2274+<th>Pascal</th>
2275+<th>JavaScript</th>
2276+</tr>
2277+</thead>
2278+<tbody>
2279+<tr>
2280+<td><code>Program MyModule;</code><br />
2281+<code>{$modeswitch externalclass}</code><br />
2282+<code>type</code><br />
2283+<code>  TJSDate = class external name 'Date'</code><br />
2284+<code>  private</code><br />
2285+<code>    function getYear: NativeInt;</code><br />
2286+<code>    procedure setYear(const AValue: NativeInt);</code><br />
2287+<code>  public</code><br />
2288+<code>    constructor New;</code><br />
2289+<code>    constructor New(const MilliSecsSince1970: NativeInt);</code><br />
2290+<code>    class function now: NativeInt;</code><br />
2291+<code>    property Year: NativeInt read getYear write setYear;</code><br />
2292+<code>  end;</code><br />
2293+<code>var</code><br />
2294+<code>  d: TJSDate;</code><br />
2295+<code>Begin</code><br />
2296+<code>  d:=TJSDate.New;</code><br />
2297+<code>  d.Year:=d.Year+1;</code><br />
2298+<code>End.</code></td>
2299+<td><code>rtl.module("program",["System"],function () {</code><br />
2300+<code>  var $mod = this;</code><br />
2301+<code>  this.d = null;</code><br />
2302+<code>  $mod.$main = function () {</code><br />
2303+<code>    $mod.d = new Date();</code><br />
2304+<code>    $mod.d.setYear($mod.d.getYear() + 1);</code><br />
2305+<code>  };</code><br />
2306+<code>});</code></td>
2307+</tr>
2308+</tbody>
2309+</table>
2310+
2311+Notes:
2312+
2313+- An external class can descend from another external class.
2314+- Any class instance can be type casted to any root class.
2315+- A Pascal class can descend from an external class.
2316+- You can define a class-of external class and the **is** and **as** operators work similar.
2317+- Class variables work as in JavaScript. That means, each descendant and each instance can have its own value. For example *TExtA.Value* might be different from *InstanceExtA.Value*. Setting *InstanceExtA.Value* does not change *TExtA.Value*.
2318+- Const with an expression are replaced by the expression.
2319+- Const without an expression are treated as a readonly variable.
2320+- Class functions and class procedures are allowed, but can only be called via the class, not via an instance.\
2321+ For example you can call the class function *TJSString.fromCharCode()*, but you cannot call *aJSString.fromCharCode()*.
2322+- Since class types are JS objects it is possible to typecast a class type to the JS Object, e.g. *TJSObject(TObject)*. Note that you cannot typecast directly to a *TJSObject* descendant in \$mode objfpc. You can use *TJSWindow(TJSObject(ExtClassInstance))*.
2323+- You can typecast function addresses and function references to JS function, e.g. *TJSFunction(@SomeProc)*, *TJSFunction(OnClick)*. Keep in mind that typecasting a method address creates a function wrapper to bind the Self argument, except when typecasting to *TJSFunction* (pas2js 1.5+).
2324+
2325+## External class as ancestor
2326+
2327+A Pascal class can descend from an external class - a JS object or function.\
2328+The methods *AfterConstruction* and *BeforeDestruction* are called if they exist.\
2329+New instances of a JS Object descendant are created by default with *Object.create(ancestorclass)*.\
2330+New instances of a JS Function descendant are created by default with *new DescendantFunc()*.\
2331+You can override this, by providing a non private\
2332+**class function NewInstance(fnname: string; const paramsarray): TPasClass; virtual;**. This method is called to create a new instance and before calling the constructor. The name is arbitrary, but the function must be the **first non private**, non external, virtual class function with the class as result type.\
2333+
2334+<table>
2335+<thead>
2336+<tr>
2337+<th>Pascal</th>
2338+<th>JavaScript</th>
2339+</tr>
2340+</thead>
2341+<tbody>
2342+<tr>
2343+<td><code>// Example for descending a Pascal class from a JS Object</code><br />
2344+<code>Program MyModule;</code><br />
2345+<code>{$modeswitch externalclass}</code><br />
2346+<code>type</code><br />
2347+<code>  TExtA = class external name 'ExtA'</code><br />
2348+<code>  end;</code><br />
2349+<code>  TMyB = class(TExtA)</code><br />
2350+<code>  protected</code><br />
2351+<code>    // optional: override default allocation</code><br />
2352+<code>    class function NewInstance(fnname: string; const paramarray): TMyB; virtual;</code><br />
2353+<code>  end;</code><br />
2354+<code>class function TMyB.NewInstance(fnname: string; const paramarray): TMyB;</code><br />
2355+<code>Begin</code><br />
2356+<code>  asm</code><br />
2357+<code>  Result = Object.create(ExtA); // that is what the rtl does</code><br />
2358+<code>  end;</code><br />
2359+<code>End;</code><br />
2360+<br />
2361+<code>Begin</code><br />
2362+<code>End.</code></td>
2363+<td><code>rtl.module("program",["System"],function () {</code><br />
2364+<code>  var $mod = this;</code><br />
2365+<code>  rtl.createClassExt($mod, "TMyB", ExtA, "NewInstance", function () {</code><br />
2366+<code>    this.$init = function () {</code><br />
2367+<code>    };</code><br />
2368+<code>    this.$final = function () {</code><br />
2369+<code>    };</code><br />
2370+<code>    this.NewInstance = function (fnname, paramarray) {</code><br />
2371+<code>      var Result = null;</code><br />
2372+<code>      Result = Object.create(ExtA);</code><br />
2373+<code>      return Result;</code><br />
2374+<code>    };</code><br />
2375+<code>  });</code><br />
2376+<code>  $mod.$main = function () {</code><br />
2377+<code>  };</code><br />
2378+<code>});</code></td>
2379+</tr>
2380+</tbody>
2381+</table>
2382+
2383+<table>
2384+<thead>
2385+<tr>
2386+<th>Pascal</th>
2387+<th>JavaScript</th>
2388+</tr>
2389+</thead>
2390+<tbody>
2391+<tr>
2392+<td><code>// Example for descending a Pascal class from a JS Function</code><br />
2393+<code>Program MyModule;</code><br />
2394+<code>{$modeswitch externalclass}</code><br />
2395+<code>uses JS;</code><br />
2396+<code>type</code><br />
2397+<code>  TExternalFunc = class external name 'ExternalFunc'(TJSFunction)</code><br />
2398+<code>    constructor New(a: word);</code><br />
2399+<code>  end;</code><br />
2400+<code>  TMyFunc = class(TExternalFunc)</code><br />
2401+<code>    constructor Create(b: word);</code><br />
2402+<code>  end;</code><br />
2403+<code>constructor TMyFunc.Create(b: word);</code><br />
2404+<code>Begin</code><br />
2405+<code>  inherited New(b+1); // optional: call inherited constructor function</code><br />
2406+<code>End;</code><br />
2407+<br />
2408+<code>var</code><br />
2409+<code>  f: TMyFunc;</code><br />
2410+<code>Begin</code><br />
2411+<code>  f:=TMyFunc.Create(3);</code><br />
2412+<code>  writeln(jsInstanceOf(f,TExternalFunc)); // writes true, instanceof operator works as expected</code><br />
2413+<code>End.</code></td>
2414+<td><code>rtl.module("program",["System","js"],function () {</code><br />
2415+<code>  var $mod = this;</code><br />
2416+<code>  rtl.createClassExt($mod, "TMyFunc", ExternalFunc, "", function () {</code><br />
2417+<code>    this.$init = function () {</code><br />
2418+<code>    };</code><br />
2419+<code>    this.$final = function () {</code><br />
2420+<code>    };</code><br />
2421+<code>    this.Create$2 = function (b) {</code><br />
2422+<code>      this.$ancestorfunc(b+1);</code><br />
2423+<code>    };</code><br />
2424+<code>  });</code><br />
2425+<code>  this.f = null;</code><br />
2426+<code>  $mod.$main = function () {</code><br />
2427+<code>    f = $mod.TMyFunc.$create("Create$2",[3]);</code><br />
2428+<code>    pas.System.Writeln(pas.JS.jsInstanceOf(f,ExternalFunc));</code><br />
2429+<code>  };</code><br />
2430+<code>});</code></td>
2431+</tr>
2432+</tbody>
2433+</table>
2434+
2435+## The JSValue type
2436+
2437+Pas2js introduces a new type **JSValue**, which works similar to a JS variable. You can assign almost any value to it and it can be type casted to many types. JSValue is useful for JS wrappers, when a variable can have multiple types. And it can be used for containers storing arbitrary data, e.g. a list of JSValue.\
2438+Key features:\
2439+
2440+- A JSValue variable initial value is undefined.
2441+- Operators: =, \<\>
2442+- type casting a *JSValue* to ...
2443+ - *Integer: Math.floor(aJSValue)* Note: may return *NaN*
2444+ - *Boolean: !(aJSValue == false)* Note: works for numbers too, *0==false*
2445+ - *Double: rtl.getNumber(aJSValue)* Note: *typeof(n)=="number"?n:NaN;*
2446+ - *String: ""+aJSValue*
2447+ - *Char: rtl.getChar(aJSValue)* Note: *((typeof(c)!="string") && (c.length==1)) ? c : ""*
2448+ - class instance or class-of: *rtl.getObject()* Note: checks for type *"object"*
2449+ - enum type
2450+ - pointer
2451+- A JSValue in a conditional expressions *If aJSValue then, while aJSValue do, repeat until aJSValue* has the same meaning as in JS: the condition is true, if the value is not *undefined, false, null, NaN, 0, ''*. Note that *new Boolean(false)* is not *null* and the condition is true.
2452+- *function Assigned(V: jsvalue): boolean* returns true if\
2453+ *(V!=undefined) && (V!=null) && (!rtl.isArray(V) \|\| (V.length \> 0))*
2454+- *function StrictEqual(const A: jsvalue; const B): boolean*
2455+- *function StrictInequal(const A: jsvalue; const B): boolean*
2456+- Any array can be assigned to an *array of jsvalue*.
2457+- is-operator: *jsvalue is class-type*, *jsvalue is class-of-type*\
2458+- The unit JS provides many utility functions for JSValue, like *hasString, hasValue, isBoolean, isNumber, isInteger, isObject, isClass, isClassInstance, etc..*
2459+
2460+## Accessing JS object properties with the bracket accessor
2461+
2462+Pas2js allows to define index properties that map directly to the JS object properties. For example the default property of TJSObject allows to get and set the properties of an object. For example *TJSObject(AnObject)\['Name'\]:=Value;*\
2463+Another example is the default property of TJSArray, that allows access via integers *aTJSArray\[3\]:=Value;*\
2464+To define your own bracket accessor define a normal index property and define the getter/setter as *external name '\[\]*'.\
2465+Here is an example for a read only accessor:
2466+
2467+<table>
2468+<thead>
2469+<tr>
2470+<th>Pascal</th>
2471+<th>JavaScript</th>
2472+</tr>
2473+</thead>
2474+<tbody>
2475+<tr>
2476+<td><code>Program MyModule;</code><br />
2477+<code>{$modeswitch externalclass}</code><br />
2478+<code>type</code><br />
2479+<code>  TExtA = class external name 'ExtA'</code><br />
2480+<code>  private</code><br />
2481+<code>    function GetItems(Index: integer): String; external name '[]';</code><br />
2482+<code>  public</code><br />
2483+<code>    property Items[Index: integer]: String read GetItems; default;</code><br />
2484+<code>  end;</code><br />
2485+<code>var</code><br />
2486+<code>  Obj: TExtA;</code><br />
2487+<code>  s: String;</code><br />
2488+<code>Begin</code><br />
2489+<code>  ... get Obj from somewhere ...</code><br />
2490+<code>  s:=Obj[2];</code><br />
2491+<code>End.</code></td>
2492+<td><code>rtl.module("program",["System"],function () {</code><br />
2493+<code>  var $mod = this;</code><br />
2494+<code>  this.Obj = undefined;</code><br />
2495+<code>  this.s = "";</code><br />
2496+<code>  $mod.$main = function () {</code><br />
2497+<code>    $mod.s = Obj[2];</code><br />
2498+<code>  };</code><br />
2499+<code>});</code></td>
2500+</tr>
2501+</tbody>
2502+</table>
2503+
2504+Notes:
2505+
2506+- A property can have a mix of normal accessor and bracket accessor. For example a bracket accessor as getter and a normal function as setter.
2507+
2508+## RTTI - Run Time Type Information
2509+
2510+The RTTI provides access to the type data of all published properties, fields and methods. The type data provides similar information as Delphi/FPC, but the internals are very different. Delphi/FPC uses pointers, variant records and fake static arrays, which have no equivalent in JS. Instead pas2js uses external classes. For example:
2511+
2512+`    TTypeInfo = class external name 'rtl.tTypeInfo'`\
2513+`    public`\
2514+`      Name: String external name 'name';`\
2515+`      Kind: TTypeKind external name 'kind';`\
2516+`    end;`\
2517+`    TTypeInfoClass = class of TTypeInfo;`\
2518+\
2519+`    TTypeInfoInteger = class external name 'rtl.tTypeInfoInteger'(TTypeInfo)`\
2520+`    public`\
2521+`      MinValue: NativeInt external name 'minvalue';`\
2522+`      MaxValue: NativeInt external name 'maxvalue';`\
2523+`      OrdType : TOrdType external name 'ordtype';`\
2524+`    end;`\
2525+
2526+The **typeinfo** function works on type, var, const and property identifiers. By default it returns a *pointer*. If the typinfo unit is used it returns the appropiate *TTypeInfo*. For instance *typeinfo(integer)* returns a *TTypeInfoInteger*.\
2527+*Typeinfo* of a *var* or *const* returns the typeinfo of its type, not of its current runtime value. The exception is a class and class-of instance variable (e.g. *var o: TObject; ... typeinfo(o)*), which returns the typeinfo of the current runtime value. If *o* is *nil* it will give a JS error.\
2528+Local types (i.e. inside a procedure) do not have typeinfo.\
2529+Open array parameters are not yet supported.\
2530+Note that FPC *typeinfo(aClassVar)* returns the compiletime type, so it works on *nil*.\
2531+
2532+## Async/AWait
2533+
2534+Pas2js supports the JS operators async and await to simplify the use of Promise. The await operator corresponds to three intrinsic Pas2js functions:
2535+
2536+- *function await(AsyncFunctionWithResultT()): T;* // implicit promise, the inner () can be omitted
2537+- *function await(aType; p: TJSPromise): aType;* // explicit promise requires the resolved type
2538+- *function await(aType; j: jsvalue): aType;* // explicit promise requires the resolved type
2539+
2540+The await function can only be used inside a procedure with the async modifier.\
2541+Example for the explicit promise:
2542+
2543+<table>
2544+<thead>
2545+<tr>
2546+<th>Pascal</th>
2547+<th>JavaScript</th>
2548+</tr>
2549+</thead>
2550+<tbody>
2551+<tr>
2552+<td><code>Program MyModule;</code><br />
2553+<br />
2554+<code>uses JS, Web;</code><br />
2555+<br />
2556+<code>function ResolveAfter2Seconds: TJSPromise;</code><br />
2557+<code>begin</code><br />
2558+<code>  Result:=TJSPromise.new(procedure(resolve, reject : TJSPromiseResolver)</code><br />
2559+<code>    begin</code><br />
2560+<code>    window.setTimeout(procedure</code><br />
2561+<code>      begin</code><br />
2562+<code>      resolve('resolved');</code><br />
2563+<code>      end,</code><br />
2564+<code>      2000); // wait 2 seconds</code><br />
2565+<code>    end);</code><br />
2566+<code>end;</code><br />
2567+<br />
2568+<code>procedure AsyncCall; async;</code><br />
2569+<code>var s: string;</code><br />
2570+<code>begin</code><br />
2571+<code>  writeln('calling');</code><br />
2572+<code>  s := await(string,resolveAfter2Seconds()); // does not check if result is really a string</code><br />
2573+<code>  writeln(s); // expected output: 'resolved'</code><br />
2574+<code>end;</code><br />
2575+<br />
2576+<code>begin</code><br />
2577+<code>  AsyncCall;</code><br />
2578+<code>end.</code></td>
2579+<td><code>rtl.module("program",["System","JS","Web"],function () {</code><br />
2580+<code>  "use strict";</code><br />
2581+<code>  var $mod = this;</code><br />
2582+<code>  this.ResolveAfter2Seconds = function () {</code><br />
2583+<code>    var Result = null;</code><br />
2584+<code>    Result = new Promise(function (resolve, reject) {</code><br />
2585+<code>      window.setTimeout(function () {</code><br />
2586+<code>        resolve("resolved");</code><br />
2587+<code>      },2000);</code><br />
2588+<code>    });</code><br />
2589+<code>    return Result;</code><br />
2590+<code>  };</code><br />
2591+<code>  this.AsyncCall = async function () {</code><br />
2592+<code>    var s = "";</code><br />
2593+<code>    pas.System.Writeln("calling");</code><br />
2594+<code>    s = await $mod.ResolveAfter2Seconds();</code><br />
2595+<code>    pas.System.Writeln(s);</code><br />
2596+<code>  };</code><br />
2597+<code>  $mod.$main = function () {</code><br />
2598+<code>    $mod.AsyncCall();</code><br />
2599+<code>  };</code><br />
2600+<code>});</code></td>
2601+</tr>
2602+</tbody>
2603+</table>
2604+
2605+Notes:
2606+
2607+- The await function does only compile time checks, no runtime checks.
2608+- Inside an async function/procedure you can pass a *TJSPromise* to the *exit()* function. For example:\
2609+ *exit(aPromise);*\
2610+ *exit(inherited);*
2611+
2612+## Compiler directives
2613+
2614+In config files:
2615+
2616+- \#IFDEF macroname
2617+- \#IFNDEF macroname
2618+- \#IF expression - same as \$if, except only defines
2619+- \#ELSEIF
2620+- \#ELSE
2621+- \#ENDIF
2622+- \#ERROR text
2623+
2624+In source files:
2625+
2626+- <span class="tt">{\$Define *MacroName*}</span>: defines macro *MacroName* with value '1'.
2627+- <span class="tt">{\$Define *MacroName:=value*}</span>: defines macro *MacroName* with custom value.
2628+- <span class="tt">{\$Undef *MacroName*}</span>: undefines macro *MacroName*.
2629+- <span class="tt">{\$IfDef *MacroName*}</span>: if *MacroName* is not defined, skip to next <span class="tt">\$Else</span> or <span class="tt">\$EndIf</span>. Can be nested.
2630+- <span class="tt">{\$IfNDef *MacroName*}</span>: as <span class="tt">\$IfDef</span>, except negated.
2631+- <span class="tt">{\$If *boolean expression*}</span>: if *expression* evaluates to true (not '0'), skip to next <span class="tt">\$Else</span> or <span class="tt">\$EndIf</span>. Can be nested.\
2632+ Supported functions and operators:\
2633+ * macro - replaced by its value, a simple define has value '1'
2634+ - defined(macro) - '1' if defined, '0' otherwise
2635+ - undefined(macro) - as <span class="tt">*not defined(macro)*</span>
2636+ - option(letter) - same as *<span class="tt">{\$IFOpt letter+}</span>*
2637+ - <span class="tt">not</span> - first level of precedence
2638+ - <span class="tt">*, /, div, mod, and, shl, shr</span> - second level of precedence
2639+ - <span class="tt">+, -, or, xor</span> - third level of precedence
2640+ - <span class="tt">=, \<\>, \<, \>, \<=, \>=</span> - fourth level of precedence
2641+ - If the operands can be converted to numbers they are combined as numbers, otherwise as strings. Not supported functions and operators:\
2642+ - <span class="tt">defined(Pascal identifier), undefined(Pascal identifier)</span>
2643+ - <span class="tt">declared(Pascal identifier)</span>
2644+ - <span class="tt">in</span> operator
2645+- <span class="tt">{\$IfOpt *Letter+,-*}</span>: if *expression* evaluates to true (not '0'), skip to next <span class="tt">\$Else</span> or <span class="tt">\$EndIf</span>. Can be nested.
2646+- <span class="tt">{\$Else}</span>: If previous <span class="tt">\$IfDef</span>, <span class="tt">\$If</span> or <span class="tt">\$IfOpt</span> was skipped, execute next block, otherwise skip.
2647+- <span class="tt">{\$ElseIf *boolean expression*}</span> : As <span class="tt">\$Else</span>, except with an extra expression like <span class="tt">\$if</span> to test. There can be multiple <span class="tt">\$elseif</span>.
2648+- <span class="tt">{\$EndIf}</span> : ends an <span class="tt">\$IfDef</span> block
2649+- <span class="tt">{\$mode delphi} or {\$mode objfpc}</span> : Same as <span class="tt">-Mdelphi</span> or <span class="tt">-Mobjfpc</span>, but only for this unit. You can use units of both modes in a program. If present must be at the top of the unit, or after the module name.
2650+- <span class="tt">{\$modeswitch externalclass}</span> : allow declaring external classes
2651+- <span class="tt">{\$modeswitch arrayoperators}</span> : allow + operator to concatenate arrays, default in mode delphi
2652+- <span class="tt">{\$modeswitch OmitRTTI}</span> : treat published sections as public
2653+- <span class="tt">{\$macro on\|off}</span> enables macro replacements. Only macros with a value are replaced. Macros are never replaced inside directives.
2654+- <span class="tt">{\$I filename} or {\$include filename}</span> - insert include file
2655+- <span class="tt">{\$I %param%}</span> :
2656+ - <span class="tt">%date%</span>: current date as string literal, '\[yyyy/mm/dd\]'
2657+ - <span class="tt">%time%</span>: current time as string literal, 'hh:mm:ss'. Note that the inclusion of <span class="tt">%date%</span> and <span class="tt">%time%</span> will not cause the compiler to recompile the unit every time it is used: the date and time will be the date and time when the unit was last compiled.
2658+ - <span class="tt">%file%</span>: current source filename as string literal, e.g. **unit1.pas**
2659+ - <span class="tt">%line%</span>: current source line number as string literal, e.g. **123**
2660+ - <span class="tt">%linenum%</span>: current source line number as integer, e.g. *123*
2661+ - <span class="tt">%currentroutine%</span>: name of current routine as string literal
2662+ - <span class="tt">%pas2jstarget%, %pas2jstargetos%, %fpctarget%, %fpctargetos%</span>: target os as string literal, e.g. 'Browser'
2663+ - <span class="tt">%pas2jstargetcpu%, %fpctargetcpu%</span>: target cpu as string literal, e.g. 'ECMAScript5'
2664+ - <span class="tt">%pas2jsversion%, %fpcversion%</span>: compiler version as strnig literal, e.g. '1.0.2'
2665+ - If param is none of the above it will use the environment variable. Keep in mind that depending on the platform the name may be case sensitive. If there is no such variable an empty string *''* is inserted.
2666+- <span class="tt">{\$Warnings on\|off}</span>
2667+- <span class="tt">{\$Notes on\|off}</span>
2668+- <span class="tt">{\$Hints on\|off}</span>
2669+- <span class="tt">{\$Error text}</span> : emit an error
2670+- <span class="tt">{\$Warning text}</span> : emit a warning
2671+- <span class="tt">{\$Note text}</span> : emit a note
2672+- <span class="tt">{\$Hint text}</span> : emit a hint
2673+- <span class="tt">{\$Message hint-text}</span> : emit a hint
2674+- <span class="tt">{\$Message hint\|note\|warn\|error\|fatal text}</span> : emit a message
2675+- <span class="tt">{\$Warn identifier on\|off\|default\|error}</span> : enable or disable a specific hint.\
2676+ Note, that some hints like "Parameter %s not used" are currently using the enable state at the end of the module, not the state at the hint source position.\
2677+ Identifier can be a message number as written by -vq or one of the following case insensitive:\
2678+ * <span class="tt">CONSTRUCTING_ABSTRACT</span> : Constructing an instance of a class with abstract methods.
2679+ - <span class="tt">IMPLICIT_VARIANTS</span> : Implicit use of the variants unit.
2680+ - <span class="tt">NO_RETVAL</span> : Function result is not set
2681+ - <span class="tt">SYMBOL_DEPRECATED</span> : Deprecated symbol.
2682+ - <span class="tt">SYMBOL_EXPERIMENTAL</span> : Experimental symbol
2683+ - <span class="tt">SYMBOL_LIBRARY</span>
2684+ - <span class="tt">SYMBOL_PLATFORM</span> : Platform-dependent symbol.
2685+ - <span class="tt">SYMBOL_UNIMPLEMENTED</span> : Unimplemented symbol.
2686+ - <span class="tt">HIDDEN_VIRTUAL</span> : method hides virtual method of ancestor
2687+ - <span class="tt">GARBAGE</span> : text after final end.
2688+ - <span class="tt">BOUNDS_ERROR</span> : range check errors
2689+ - <span class="tt">MESSAGE_DIRECTIVE</span> : user defined \$message
2690+- <span class="tt">{\$M+}, {\$TypeInfo on}</span> : switches default visibility for class members from public to published
2691+- <span class="tt">{\$ScopedEnums on\|off}</span> disabled(default): propagate enums to global scope, enable: needs fqn e.g. TEnumType.EnumValue.
2692+- <span class="tt">{\$C+}</span> generate code for assertions
2693+- <span class="tt">{\$H+}</span> , but not <span class="tt">{\$H-}</span>
2694+- <span class="tt">{\$J-}, {\$WriteableConst off}</span> : Typed const become readonly. For example *const i:byte=3; ... i:=4* creates a compile time error.
2695+- <span class="tt">{\$M+}</span> : allow published members
2696+- <span class="tt">{\$Q+}</span> : not yet supported, ignored
2697+- <span class="tt">{\$R+}, {\$RangeChecks on}</span> : compile time range check hints become errors and add runtime range checks for assignments.
2698+- <span class="tt">{\$ObjectChecks on\|off}</span> :
2699+ - Verify method calls, i.e. check at runtime in every method if *Self* is a descendant class.
2700+ - Check type casts, e.g. *TBird(AnObject)* becomes *AnObject as TBird*
2701+- <span class="tt">{\$DispatchField Msg}</span> : enable checking *message number* methods for record field name "Msg"
2702+- <span class="tt">{\$DispatchStrField MsgStr}</span> : enable checking *message string* methods for record field name "Msg"
2703+- <span class="tt">{\$Optimization Name}</span> : same as command line option -OoName
2704+- <span class="tt">{\$linklib filename \[alias\]}</span>:
2705+ - <span class="tt">filename</span> filename to import.
2706+ - <span class="tt">alias</span> alias for this import. Must be a pascal identifier. If no alias is specified, the last part of the filename is used, all non-alphanumeric characters are converted to underscores.
2707+
2708+Defines:
2709+
2710+- PAS2JS
2711+- PAS2JS_FULLVERSION - major*1000+minor*100+release, e.g. 1.2.3 = 10203
2712+- Target platform: Browser, NodeJS, Pas2JSTargetOS=\<value\>
2713+- Target processor: ECMAScript5, ECMAScript6, ECMAScript=5, Pas2JSTargetCPU=\<value\>
2714+- Mode: DELPHI, OBJFPC
2715+
2716+## Numbers
2717+
2718+`JavaScript only supports double. All Pascal number types and enum values are mapped to this. A double supports integers from`\
2719+` MinInteger = -$10000000000000;`\
2720+` MaxInteger = $fffffffffffff;`\
2721+` MinDouble = 5.0e-324;`\
2722+` MaxDouble = 1.7e+308;`\
2723+\
2724+` Intrinsic integer types:`
2725+
2726+- Byte - unsigned 8-bit
2727+- ShortInt - signed 8-bit
2728+- Word - unsigned 16-bit
2729+- SmallInt - signed 16-bit
2730+- LongWord - unsigned 32-bit
2731+- LongInt - signed 32-bit
2732+- NativeUInt - unsigned 53-bit
2733+- NativeInt - signed 54-bit
2734+
2735+Notes:
2736+
2737+- Division by zero does not raise an exception. 0/0 results in NaN, positive/0 is Infinity, negative/0 is -Infinity.
2738+- NaN\<\>NaN
2739+- Overflows work differently. For example in Delphi adding 100 to a byte of 200 gives *300 and \$ff = 44*, while in pas2js it gives 300, which is not a byte anymore.
2740+- Math.isNan(double) tests for NaN. Otherwise false. isNan(Infinity)=false.
2741+- Math.isFinite(double) tests if not NaN, positive or negative infinity.
2742+- Math.isInfinite(double) tests if positive or negative infinity.
2743+- For more functions see unit Math.
2744+- To make porting easier Single is defined in the system unit as alias of double, but gives a warning. Since using higher precision might give unexpected results you should check every place.
2745+
2746+## Other supported Pascal elements
2747+
2748+- **break**, **continue**, **exit**, **exit()**
2749+- **chr**, **ord**
2750+- alias type and type alias type
2751+- *inc()* and *dec()* to += -=
2752+- Converts "a div b" to "Math.floor(a / b)"
2753+- and, or, xor, not: logical and bitwise
2754+- Name conflicts with JS identifiers are automatically fixed by changing case. For example a Pascal function "*apply"* is renamed to "*Apply*".
2755+- uses unitname in 'filename'. In *\$mode delphi* the in-filenames are only allowed in the program and the unitname must fit the filename, e.g. *uses unit1 in 'sub/Unit1.pas*.\
2756+ In *\$mode objfpc* units can use in-filenames too and alias are allowed, e.g. *uses foo in 'bar.pas*'.
2757+- The intrinsic procedure **str** works with boolean, integer, float and enumvalue.\
2758+ Additionally there is **str** function, that takes an arbitrary number of arguments and returns a concatenated string. It supports string as parameter too. For example s:=str(i,' ',d:1:5).\
2759+ Width and precision is supported. str(i:10) will add spaces to the left to fill up to 10 characters. str(aDouble:1:5) returns a string in decimal format with 5 digits for the fraction.
2760+- Intrinsic procedure WriteStr(out s: string; params...)
2761+- *Debugger;* converts to *debugger;*. If a debugger is running it will break on this line just like a break point.
2762+- *function concat(string1,string2,...): string* since 1.3
2763+- *\$mode delphi: function lo\|hi(integer): byte* since 1.3
2764+- *\$mode objfpc: function lo\|hi(integer): byte\|word\|longword* since 1.3
2765+- *function GetTypeKind(Type or Var): TTypeKind;* since 1.5
2766+
2767+## Not supported elements
2768+
2769+- Class destructor
2770+- Enums with custom values
2771+- Global properties
2772+- Futures
2773+- Inline
2774+- Objects
2775+- Operator overloading
2776+- Pointer arithmetic
2777+- Package
2778+- Resources
2779+- RTTI extended, \$RTTI
2780+- Variant records
2781+- Variants
2782+
2783+## JavaScript Version
2784+
2785+Code generation depending on -P option:
2786+
2787+- ECMAScript5
2788+- ECMAScript6: using 0b for binary literals, and 0o for octal literals
2789+
2790+## Creating source maps
2791+
2792+Source maps are files telling the browser what JavaScript comes from which original source (e.g. Pascal file), similar to debug information in FPC/Delphi.\
2793+In 2017 FireFox and Chrome supports source maps.\
2794+You can enable generating source map files by using the *-Jm* option.\
2795+The compiler generates one module.js.map file for every generated module.js file. The last line of the .js file contains the line\
2796+*//# sourceMappingURL=module.js.map*\
2797+telling the browser where to find the source map.\
2798+The source map contains references to the Pascal files and included .js files (e.g. -Jirtl.js) relative to the location of the source map. Note that if the Pascal file lies in a parent directory, the relativ path contains '../'. You can change the base directory of the relative paths by using the option *-Jmbasedir=\<x\>*. For example *-JmC:\www\pas* creates paths relative to C:\www\pas.\
2799+You can set the base URL, where the browser finds the Pascal sources, by passing the *-Jmsourceroot=\<x\>* option. For example *-Jmsourceroot=<http://www.yoursite.com/pas/>*. The browser prepends this to the source map filenames when downloading the original source files (e.g. the .pas files).\
2800+You can include the whole Pascal sources in the source map using the option *-Jminclude*.\
2801+\
2802+To show the generated mapping for each line you can use the tool fpc/packages/fcl-js/examples/srcmapdump.\
2803+
2804+- Option -JmXSSIHeader: According to the specifications sourcemap should start with the XSSI (cross site script inclusion) protection header *)\]}*'. If your browser does not support that, disable it with *-JmXSSIHeader-*. See here the specs: <https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.h7yy76c5il9v>
2805+
2806+## See Also
2807+
2808+- [[pas2js]]
2809+
2810+---
2811+*From the Free Pascal wiki, page "Pas2js Transpiler", as it stood on 2023-05-08 after a change by Maxerist, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
2812+Category: Pas2js

Back to history