Pas2js Package

From Free Pascal wiki
Revision as of 17:38, 16 January 2023 by Mattias2 (talk | contribs) (Created page with "=Overview= This is a proposal for pas2js packages, working similar to FPC/Delphi packages. A pas2js package has a pascal source starting with keyword '''package''' instead o...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

Overview

This is a proposal for pas2js packages, working similar to FPC/Delphi packages.

A pas2js package has a pascal source starting with keyword package instead of program, and it has an optional requires and contains clause.

Compiling a package

When pas2js compiles a package, it generates a pkgname.ppmd, a pkgname.js and optionally a pkgname.js.map file. A ppmd stands for "pas2js package meta data".

  • Options -FU, -FE and -o apply canonically.
  • Option -Jc has no effect.

PPMD

The ppmd is a json file and contains the package units including their sources, plus data about specializations (specialized generics) and whatever else is needed.

Specializations

Each pas2js package can have its own specializations - same as in Delphi:

  • Two dependent packages use the same TList<TExample>.
  • Two independent packages B and C might have two different TList<TExample>. For example package A defines a TExample, and there is no TList<TExample> in A, and packages B and C both use A and define TList<TExample>, then there are two different TList<TExample>, although they have the same name.

Contains

All units of a package must be listed in the contains clause Contrary to Delphi if a package uses a unit outside a package pas2js creates an error. This means a package can only use packaged units.

Requires

Lists all packages needed by the package.

Using a package

Compiling a program/library with packages:

pas2js gets a new command line option -Fp<pkgname;pkgnam;...> to specify the packages of a program/library and -FP<dir;dir;...> to add directories to the package search path. pas2js searches the ppmd files first in the -FP search paths and then in the unit search paths given by -Fu. It loads all the ppmd recursively. Then it starts the normal compilation, reading all units, searching units first in the packages, then in the unit path.

Then it generates js only for the program sources.

The html needs to load all js files of the packages and the program.

The -Jc option

If -Jc is given when compiling a program with packages pas2js concatenates all the package js and the program into one js (generating a big js.map).

Without -Jc pas2js concatenates all program js, leaving out the packages.

Optimizations

With precompiled package js files pas2js cannot remove unneeded code from the packages, as it does not yet have any post-js optimization. Theoretically since the packages contain all the sources, it could generate a program the current way (not using the package js files).

Dynamic loading

Packages can be loaded after the program was loaded.

Unloading is not supported (yet) as this requires more bookkeeping what was loaded.

Implementation

ToDos

  • Scanner: list of used files
  • Parser: package, requires, contains
  • Compiler: Read -Fp and -FP options
  • Compiler: Read recursively ppmd files
  • Resolver: mark specializations in packages, generate lists for each package,
  • Pas2js Resolver: compute the place where the specialization is created (near first occurrence)
  • Analyzer: when compiling a package mark all public/protected declarations of package units
  • Converter:
    • create package js containing requires, contains and delayed specializations
    • create package specializations (the generic is in another package)
      • many changes to access of local variables, e.g. the declarations of the generic unit
  • With -Jc: generate all js into one file - similar to static linking. Omitting not needed elements
  • Without -Jc: generate all program/library modules into one js.
  • libpas2js hooks:
    • after loading an unit source from ppmd, for decryption
    • before saving an unit source to ppmd, for encryption
    • after loading ppmd, for reading custom data
    • before saving ppmd, for writing custom data