-
Notifications
You must be signed in to change notification settings - Fork 261
JEP Linker
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:
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'
}
/>
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
.
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 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 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 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 } />
In this iteration graph is fork-joined for external
type nodes
that were not located (node located
is false
). We do this
several times, once per fallback algorithm:
Assuming that user meant system module we fork-join sub-graph to
refine nodes that can be discovered in add-on SDK lib
:
{
requirement: 'tabs',
requirer: './main.js',
root: './addon',
type: 'deprecated',
correction: { type: 'system', requirement: '@tabs' },
path: './sdk/tabs.js',
located: true
}
Assuming that user meant local module (located relative to a
requirer) we fork-join sub-graph to refine nodes that can be
found under the node path
resolved to it's requirer
:
{ requirement: 'foo/bar', requirer: './main.js', root: './addon', type: 'deprecated', correction: { type: 'local', requirement: './foo/bar' }, path: './foo/bar.js', located: true }
If we run linker in test mode we fork-join sub-graph to refine
nodes that could have being discovered if we were running cfx test
in older versions of cfx. If node path
relative to add-on root
exists we enhance node accordingly.
In this iteration we filter graph by nodes of deprecated
type and
log deprecation warnings with instructions of correct requirement
forms. Then we filter graph by all non-system type nodes that could
not be located report errors and quit.
In this iteration we traverse nested requirements by processing each node through linker process described by this document. Once we're done traversing a tree we flatten in down.
In this iteration we normalize manifest to standard compilation ready form MOST LIKELY TO A CURRENT MANIFEST FORM, BUT NEED TO STUDY IT FIRST