translation.html 103 KB

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