Difference between revisions of "pas2js modules"

From Lazarus wiki
Jump to navigationJump to search
 
(7 intermediate revisions by 2 users not shown)
Line 1: Line 1:
== Module import ==
+
= Module import =
 
 
  
 
pas2js can convert the '''$linklib''' directive to a JS import statement:
 
pas2js can convert the '''$linklib''' directive to a JS import statement:
Line 42: Line 41:
 
diverge.
 
diverge.
  
== Demos ==
+
= Demos =
  
 
The pas2js demos/modules directory contains a series of subdirectories. Each subdirectory has 1 demo. Compile with the command-line as above:
 
The pas2js demos/modules directory contains a series of subdirectories. Each subdirectory has 1 demo. Compile with the command-line as above:
Line 50: Line 49:
 
</code>
 
</code>
  
=== Basic ===
+
== Basic ==
  
 
This shows a simple program, no units, that uses the linklib directive to
 
This shows a simple program, no units, that uses the linklib directive to
Line 56: Line 55:
 
the exported symbols from the modules.
 
the exported symbols from the modules.
  
=== Basic-Units ===
+
== Basic-Units ==
  
 
This is the same as the Basic  example, but the import definitions are split
 
This is the same as the Basic  example, but the import definitions are split
 
out in units.
 
out in units.
  
=== Flat ===
+
== Flat ==
  
 
This shows a simple program, no units, that uses the linklib directive to
 
This shows a simple program, no units, that uses the linklib directive to
Line 67: Line 66:
 
the exported symbols from the modules; no external class is used.
 
the exported symbols from the modules; no external class is used.
  
=== Flat-Units ===
+
== Flat-Units ==
  
 
This is the same as the flat example, but the import definitions are split
 
This is the same as the flat example, but the import definitions are split
 
out in units.
 
out in units.
  
== Module export ==
+
= Module export =
 
Module export is implemented using the existing pascal '''Library''' concept.
 
Module export is implemented using the existing pascal '''Library''' concept.
  
Line 84: Line 83:
 
procedure Swim(w: word);
 
procedure Swim(w: word);
 
begin
 
begin
 +
  writeln('Swimming ',w,' meters');
 
end;
 
end;
 
exports
 
exports
Line 92: Line 92:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Compiled with ''"pas2js -Tmodule fish.pas"'' generates the following ''fish.js'':
+
Compiled with ''"pas2js -Tmodule -Jirtl.js -Jc fish.pas"'' generates the following ''fish.js'':
  
 
<syntaxhighlight lang=javascript>
 
<syntaxhighlight lang=javascript>
Line 99: Line 99:
 
   var $mod = this;
 
   var $mod = this;
 
   this.Swim = function (w) {
 
   this.Swim = function (w) {
 +
    pas.System.Writeln("Swimming ",w," meters");
 
   };
 
   };
 
   $mod.$main = function () {
 
   $mod.$main = function () {
Line 108: Line 109:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
HTML:
+
=Using a Pascal Library=
 +
 
 +
Javascript modules can be used using the Javascript [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import import] statement.
 +
 
 +
Consider the following HTML:
 
<syntaxhighlight lang=html>
 
<syntaxhighlight lang=html>
 
<!DOCTYPE html>
 
<!DOCTYPE html>
Line 122: Line 127:
 
</html>
 
</html>
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
Note that the script has type '''module''', and that no script tag with the '''rtl.run();''' statement is present in the HTML body.
 +
It is not possible to use or import a module from a regular script tag.
 +
 +
==Using Pascal Library from JavaScript==
 +
 +
The imports from a pascal library are no different from a regular Javascript import.
 +
 +
Taking the above HTML as the example, if the file '''swim.js''' contains the following javascript:
 +
 +
<syntaxhighlight lang="javascript">
 +
import Swim from "fish.js";
 +
 +
Swim(10);
 +
</syntaxhighlight>
 +
 +
Then the browser console will show the output of the program:
 +
 +
    Swimming 10 meters
 +
 +
==Using Pascal Library from Pascal==
 +
 +
As mentioned above, using a Pascal produced library from pascal is done no different from using a Javascript module,
 +
and is no different from using a library in a native program. Our 'fish' library can be used using the following program:
 +
 +
<syntaxhighlight lang="pascal">
 +
// Import the functions in an object called aqua
 +
{$linklib ./fish.js aqua}
 +
 +
// We use the aqua object name in the external:
 +
procedure Swim(aMeters: word); external name 'aqua.Swim';
 +
procedure SwimHarder(aMeters: word); external name 'aqua.Move';
 +
 +
begin
 +
  Swim(3);
 +
  SwimHarder(10);
 +
end.
 +
</syntaxhighlight>
 +
compile using the module target:
 +
 +
    <code>pas2js -Tmodule -Jc -Jirtl.js swim.lpr</code>
 +
 +
Again, the output will be shown on the console.
 +
 +
You can find another example in the pas2js [https://gitlab.com/freepascal.org/fpc/pas2js/-/tree/main/demo/library Pas2JS demos]
 +
 +
= Navigation =
 +
* Back to [[pas2js]]
 +
* Back to [[lazarus pas2js integration]]
 +
 +
[[Category:Pas2js]]
 +
 +
Note that we made a pascal program for the swim.js, but we could just as well have made a library.

Latest revision as of 00:41, 23 February 2022

Module import

pas2js can convert the $linklib directive to a JS import statement:

The following:

{$linklib ./modules/canvas.js canvas}

is converted to

import * as canvas from "./modules/canvas.js";

If the alias is omitted, one is constructed for you:

{$linklib ./modules/some-api.js}

is converted to import * as some_api from "./modules/some-api.js";

The import statements are always inserted in the main program. This is because modules are like windows libraries: self-contained programs, which only import and export well-defined symbols.

For this reason, a new target "operating system" has been invented: the module. This means that you must compile with target module:

pas2js -Tmodule -Jirtl.js main.pp

The nodejs target will also work, but in the future the 2 targets may diverge.

Demos

The pas2js demos/modules directory contains a series of subdirectories. Each subdirectory has 1 demo. Compile with the command-line as above:

pas2js -Tmodule -Jirtl.js main.pp

Basic

This shows a simple program, no units, that uses the linklib directive to import a javascript module. It uses an external class definition to access the exported symbols from the modules.

Basic-Units

This is the same as the Basic example, but the import definitions are split out in units.

Flat

This shows a simple program, no units, that uses the linklib directive to import a javascript module. It uses only external 'name' definitions to access the exported symbols from the modules; no external class is used.

Flat-Units

This is the same as the flat example, but the import definitions are split out in units.

Module export

Module export is implemented using the existing pascal Library concept.

A pas2js library is transpiled into a Javascript module with its own rtl.js and rtl.run. It can export global functions, static methods, and global variables.

For example a library exporting a function twice, as name Swim and as Move:

library Fish;
procedure Swim(w: word);
begin
  writeln('Swimming ',w,' meters'); 
end;
exports
  Swim;
  Swim name 'Move';
begin
end.

Compiled with "pas2js -Tmodule -Jirtl.js -Jc fish.pas" generates the following fish.js:

...rtl.js and system unit...
rtl.module("library", [], function () {
  var $mod = this;
  this.Swim = function (w) {
    pas.System.Writeln("Swimming ",w," meters");
  };
  $mod.$main = function () {
  };
});
rtl.run("library");
export const Swim = pas.library.Swim;
export const Move = pas.library.Swim;

Using a Pascal Library

Javascript modules can be used using the Javascript import statement.

Consider the following HTML:

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <title>Basic Pas2JS library example</title>
    <script type="module" src="fish.js"></script>
  </head>
  <body>

  </body>
</html>

Note that the script has type module, and that no script tag with the rtl.run(); statement is present in the HTML body. It is not possible to use or import a module from a regular script tag.

Using Pascal Library from JavaScript

The imports from a pascal library are no different from a regular Javascript import.

Taking the above HTML as the example, if the file swim.js contains the following javascript:

import Swim from "fish.js";

Swim(10);

Then the browser console will show the output of the program:

   Swimming 10 meters

Using Pascal Library from Pascal

As mentioned above, using a Pascal produced library from pascal is done no different from using a Javascript module, and is no different from using a library in a native program. Our 'fish' library can be used using the following program:

// Import the functions in an object called aqua
{$linklib ./fish.js aqua}

// We use the aqua object name in the external:
procedure Swim(aMeters: word); external name 'aqua.Swim';
procedure SwimHarder(aMeters: word); external name 'aqua.Move';

begin
  Swim(3);
  SwimHarder(10);
end.

compile using the module target:

   pas2js -Tmodule -Jc -Jirtl.js swim.lpr

Again, the output will be shown on the console.

You can find another example in the pas2js Pas2JS demos

Navigation

Note that we made a pascal program for the swim.js, but we could just as well have made a library.