Skip to content
This repository has been archived by the owner on Feb 26, 2022. It is now read-only.

JEP Linker

Gozala edited this page Mar 29, 2012 · 11 revisions

This page describes linker process that will be used by cfx-js to build an add-on manifest. Linker will perform multiple iterations of graph refinements before reaching a final manifest format. Following sections describe iterations and expected results:

1. Extraction of requirements

Linker takes add-on's root path and entry point module path (relative to the add-on root) as an arguments and starts building a graph for the given module. Linker reads module source, and extracts requirements to spit out stream of requirement nodes:

link('./main.js', './addon/')

<stream
{
  requirement: './utils',
  requirer: './main.js',
  root: './addon/'
}
{
  requirement: '@panel',
  requirer: './main.js',
  root: './addon/'
}
{
  requirement: '@devtools/scratchpad',
  requirer: './main.js',
  root: './addon/'
}
{
  requirement: 'fs',
  requirer: './main.js',
  root: './addon'
}
{
  requirement: 'tabs',
  requirer: './main.js',
  root: './addon',
}
{
  requirement: 'foo/bar',
  requirer: './main.js',
  root: './addon'
}
/>

2. Requirement type detection

In this iteration node of the generate graph are expanded to include information about requirement type ('local', 'system', 'remote') and expected paths:

<stream
{
  requirement: './utils',
  requirer: './main.js',
  root: './addon/',
  type: 'local',
  path: './utils.js'
}
{
  requirement: '@panel',
  requirer: './main.js',
  root: './addon/'
  type: 'system',
  path: './std/panel.js'
}
{
  requirement: '@devtools/scratchpad',
  requirer: './main.js',
  root: './addon/,
  type: 'system',
  path: './devtools/scratchpad.js'
}
{
  requirement: 'fs',
  requirer: './main.js',
  root: './addon',
  type: 'external',
  path: './fs.js'
}
{
  requirement: 'tabs',
  requirer: './main.js',
  root: './addon',
  type: 'external',
  path: './tabs.js'
}
{
  requirement: 'foo/bar',
  requirer: './main.js',
  root: './addon',
  type: 'external',
  path: './foo/bar.js'
}
/>

Note: path on 'local' and 'external' nodes are relative to add-on root. For 'system' nodes it is relative to an add-on SDK lib.

3. Locating requirements

In this iteration linker locates module requirements from graph in the filesystem. This process is type specific, so requirements grpah is fork-joined by a node types.

local

Local requirements are located under the node path relative to the add-on root. Nodes are expanded with an information of file existence:

<stream
{
  requirement: './utils',
  requirer: './main.js',
  root: './addon/',
  type: 'local',
  path: './utils.js',
  located: true
}
/>

system

System requirements are located under the node path relative to the add-on SDK lib. Nodes are expanded with an information of file existence:

<stream
{
  requirement: '@panel',
  requirer: './main.js',
  root: './addon/'
  type: 'system',
  path: './sdk/panel.js',
  located: true
}
{
  requirement: '@devtools/scratchpad',
  requirer: './main.js',
  root: './addon/,
  type: 'system',
  path: './devtools/scratchpad.js',
  located: false
}
/>

external

External dependencies are located under under the node path relative to @modules directory in an add-on root. Nodes are expanded with an information of file existence:

<stream { requirement: 'fs', requirer: './main.js', root: './addon', type: 'external', path: './fs.js', located: true } { requirement: 'tabs', requirer: './main.js', root: './addon', type: 'external', path: './tabs.js', located: false } { requirement: 'foo/bar', requirer: './main.js', root: './addon', type: 'external', path: './foo/bar.js', located: false } />

4. Backwards compatibility

In this iteration graph is fork-joined for nodes that were not located (node located is false). Graph is also fork-joined by node type.

local

If graph contains local dependency that was not located, linker exits with error that says that given requirement for the given module is missing.

system

For system modules we log a message that says that add-on will expect to have a given module in the system.

remote

On missing remote modules we make several attempt of locating them only for backwards compatibility:

system ?

Assuming that user meant system module we fork-join sub-graph to refine nodes that meant system modules instead. If modules are discovered in add-on SDK lib node's are expanded with an appropriate information:

{
  requirement: 'tabs',
  requirer: './main.js',
  root: './addon',
  type: 'deprecated',
  correction: { type: 'system', requirement: '@tabs' },
  path: './sdk/tabs.js',
  located: true
}

local ?

Assuming that user meant local module we fork-join sub-graph to refine nodes that meant system modules instead. If modules are discovered in add-on SDK lib node's are expanded with an appropriate information:

{ requirement: 'foo/bar', requirer: './main.js', root: './addon', type: 'deprecated', correction: { type: 'local', requirement: './foo/bar' }, path: './foo/bar.js', located: true }

test magic ?

If we run linker for test mode we fork-join sub-graph to refine nodes that could have being discovered if we were running cfx test in older cfx-py. If node path exists relative to add-on root we we enhance node accordingly.