Welcome to mirror list, hosted at ThFree Co, Russian Federation.

ModuleJob.js « loader « internal « lib - github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: db4cb6ae5c50315fa8defcb6c5bc92e7b2648d14 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
'use strict';

const { SafeSet, SafePromise } = require('internal/safe_globals');
const resolvedPromise = SafePromise.resolve();
const resolvedArrayPromise = SafePromise.resolve([]);
const { ModuleWrap } = require('internal/loader/ModuleWrap');

const NOOP = () => { /* No-op */ };
class ModuleJob {
  /**
   * @param {module: ModuleWrap?, compiled: Promise} moduleProvider
   */
  constructor(loader, moduleProvider, url) {
    this.url = `${moduleProvider.url}`;
    this.moduleProvider = moduleProvider;
    this.loader = loader;
    this.error = null;
    this.hadError = false;

    if (moduleProvider instanceof ModuleWrap !== true) {
      // linked == promise for dependency jobs, with module populated,
      // module wrapper linked
      this.modulePromise = this.moduleProvider.createModule();
      this.module = undefined;
      const linked = async () => {
        const dependencyJobs = [];
        this.module = await this.modulePromise;
        this.module.link(async (dependencySpecifier) => {
          const dependencyJobPromise =
            this.loader.getModuleJob(this, dependencySpecifier);
          dependencyJobs.push(dependencyJobPromise);
          const dependencyJob = await dependencyJobPromise;
          return dependencyJob.modulePromise;
        });
        return SafePromise.all(dependencyJobs);
      };
      this.linked = linked();

      // instantiated == deep dependency jobs wrappers instantiated,
      //module wrapper instantiated
      this.instantiated = undefined;
    } else {
      const getModuleProvider = async () => moduleProvider;
      this.modulePromise = getModuleProvider();
      this.moduleProvider = { finish: NOOP };
      this.module = moduleProvider;
      this.linked = resolvedArrayPromise;
      this.instantiated = this.modulePromise;
    }
  }

  instantiate() {
    if (this.instantiated) {
      return this.instantiated;
    }
    return this.instantiated = new Promise(async (resolve, reject) => {
      const jobsInGraph = new SafeSet();
      let jobsReadyToInstantiate = 0;
      // (this must be sync for counter to work)
      const queueJob = (moduleJob) => {
        if (jobsInGraph.has(moduleJob)) {
          return;
        }
        jobsInGraph.add(moduleJob);
        moduleJob.linked.then((dependencyJobs) => {
          for (const dependencyJob of dependencyJobs) {
            queueJob(dependencyJob);
          }
          checkComplete();
        }, (e) => {
          if (!this.hadError) {
            this.error = e;
            this.hadError = true;
          }
          checkComplete();
        });
      };
      const checkComplete = () => {
        if (++jobsReadyToInstantiate === jobsInGraph.size) {
          // I believe we only throw once the whole tree is finished loading?
          // or should the error bail early, leaving entire tree to still load?
          if (this.hadError) {
            reject(this.error);
          } else {
            try {
              this.module.instantiate();
              for (const dependencyJob of jobsInGraph) {
                dependencyJob.instantiated = resolvedPromise;
              }
              resolve(this.module);
            } catch (e) {
              e.stack;
              reject(e);
            }
          }
        }
      };
      queueJob(this);
    });
  }

  async run() {
    const module = await this.instantiate();
    try {
      module.evaluate();
    } catch (e) {
      e.stack;
      this.hadError = true;
      this.error = e;
      throw e;
    }
    return module;
  }
}
Object.setPrototypeOf(ModuleJob.prototype, null);
module.exports = ModuleJob;