• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OpenNTF / dojo-webpack-plugin / 317

29 Sep 2023 06:50PM UTC coverage: 98.314% (-0.1%) from 98.435%
317

push

travis-pro

web-flow
Merge pull request #377 from dpwatrous/dpwatrous/generate-bugfix

Fix error in DojoAMDRuntimeModule

521 of 541 branches covered (0.0%)

Branch coverage included in aggregate %.

2 of 2 new or added lines in 1 file covered. (100.0%)

1053 of 1060 relevant lines covered (99.34%)

1892.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.37
/lib/DojoAMDRuntimeModule.js
1
const util = require('util');
1✔
2
const {Template, RuntimeModule} = require("webpack");
1✔
3
const {getPluginProps, pluginName} = require("./DojoAMDPlugin");
1✔
4
const runtime = require("../runtime/DojoAMDMainTemplate.runtime");
1✔
5
const loaderMainModulePatch = require("../runtime/DojoLoaderNonLocalMainPatch.runtime");
1✔
6
const stringify = require("node-stringify");
1✔
7

8
class DojoAMDRuntimeModule extends RuntimeModule {
9
        constructor(chunk, set__, compiler) {
10
                super(pluginName, RuntimeModule.STAGE_BASIC);
385✔
11
                this.chunk = chunk;
385✔
12
                this.pluginProps = getPluginProps(compiler);
385✔
13
                this.options = this.pluginProps.options;
385✔
14
                compiler.hooks.afterCompile.tap(pluginName, () => {
385✔
15
                  if (this.getNumberOfErrors()) {
381✔
16
                                throw this.getErrors()[0];
3✔
17
                        }
18
                });
19
        }
20

21
        /**
22
         * @returns {string} runtime code
23
         */
24
        generate() {
25
                const pluginProps = getPluginProps(this.compilation.compiler);
387✔
26
                if (!pluginProps) {
387!
27
                        return;
×
28
                }
29
                const djProp = `__webpack_require__.${this.options.requireFnPropName}`;
387✔
30
                const [runtimeSource, asyncSource] = ['main', 'async'].map(type => Template.getFunctionContent(runtime[type])
774✔
31
                                           .replace(/__async__/g, (!!this.options.async).toString())
32
                                           .replace('__webpack_require__.dj', djProp));
33
                const chunkLoadingGlobal = JSON.stringify(this.compilation.outputOptions.chunkLoadingGlobal);
387✔
34
                const buf = [];
387✔
35
                const chunkGraph = this.chunkGraph || this.compilation.chunkGraph;
387!
36

37
                buf.push(runtimeSource);
387✔
38
                if (this.options.async) {
387✔
39
                        buf.push(asyncSource);
135✔
40
                }
41
                buf.push("var globalObj = this||window;");
387✔
42
                buf.push("registerAbsMids({");
387✔
43
                buf.push(pluginProps.hooks.renderAbsMids.call("", this.chunk, chunkGraph));
387✔
44
                buf.push("});");
387✔
45
                buf.push("");
387✔
46
                buf.push(pluginProps.hooks.dojoGlobalRequire.call("globalObj.require = req;"));
387✔
47
                buf.push(Template.indent(
387✔
48
                        `(self[${chunkLoadingGlobal}] = self[${chunkLoadingGlobal}] || []).registerAbsMids = registerAbsMids;`
49
                ));
50
                buf.push("");
387✔
51
                buf.push("// expose the Dojo compatibility functions as a properties of __webpack_require__");
387✔
52
                buf.push(`if (${djProp} && ${djProp}.name !== '${pluginName}') throw new Error("${djProp} name collision.")`);
387✔
53
                buf.push(`${djProp} = {`);
387✔
54
                buf.push(Template.indent([
387✔
55
                        `name: '${pluginName}',`,
56
                        "r: req,",
57
                        "c: createContextRequire,",
58
                        "m: dojoModuleFromWebpackModule,",
59
                        "h: resolveTernaryHasExpression,"
60
                ]));
61
                if (this.options.async) {
387✔
62
                        buf.push(Template.indent([
135✔
63
                                "d: asyncDefineModule,",
64
                                "w: wrapPromises,",
65
                                "u: unwrapPromises"
66
                        ]));
67
                }
68
                buf.push("};");
387✔
69
                buf.push("var loaderScope = Object.create(globalObj, {");
387✔
70
                buf.push("   document:{value: globalObj.document},");
387✔
71
                buf.push("});");
387✔
72
                buf.push("Object.defineProperties(loaderScope, {");
387✔
73
                buf.push("   window:{value:loaderScope},");
387✔
74
                buf.push("   global:{value:loaderScope}");
387✔
75
                buf.push("});");
387✔
76
                // Remove evidence of any existing AMD loader or else the Dojo loader won't initialize properly.
77
                buf.push("loaderScope.define = loaderScope.require = undefined");
387✔
78

79
                const dojoLoaderModule = this.getDojoLoaderModule();
387✔
80
                buf.push(`globalObj.dojoConfig = globalObj.dojoConfig || {}`);
387✔
81
                var loaderScope;
82
                if (!pluginProps.embeddedLoaderHasConfigApi) {
387✔
83
                        if (!util.isString(this.options.loaderConfig)) {
27✔
84
                                let loaderConfig = this.options.loaderConfig;
21✔
85
                                if (typeof loaderConfig === 'function') {
21✔
86
                                        loaderConfig = loaderConfig(this.options.environment || {});
15✔
87
                                }
88
                                loaderScope = pluginProps.hooks.createDojoLoaderScope.call(Object.assign({}, loaderConfig), pluginProps.dojoLoader, pluginProps.dojoLoaderFilename);
21✔
89
                        } else {
90
                                const error = new Error(`The embedded Dojo loader needs the config API in order to support loading the Dojo loader config as a module, \
6✔
91
but the loader specified at ${pluginProps.embeddedLoaderFilename} was built without the config API.  Please rebuild the embedded loader with 'dojo-config-api' feature enabled`);
92
                                this.addError(error);
6✔
93
                                throw error;
6✔
94
                        }
95
                }
96
                buf.push(this.renderDojoConfigVars(loaderScope));
381✔
97
                buf.push("var dojoLoader = __webpack_require__(" + JSON.stringify(chunkGraph.getModuleId(dojoLoaderModule)) + ");");
381✔
98
                buf.push("dojoLoader.call(loaderScope, userConfig, defaultConfig, loaderScope, loaderScope);");
381✔
99
                if (loaderScope) {
381✔
100
                        // loaderProps.baseUrl is set by the loader config renderer if the loader has no config api.
101
                        buf.push("loaderScope.require.baseUrl = " + JSON.stringify(loaderScope.require.baseUrl) + ";");
21✔
102
                }
103
                buf.push(Template.getFunctionContent(loaderMainModulePatch));
381✔
104
                buf.push("['baseUrl','has','rawConfig','on','signal'].forEach(function(name) {req[name] = loaderScope.require[name]})");
381✔
105
                const loaderConfig = pluginProps.hooks.getDojoConfig.call();
381✔
106
                if (loaderConfig.has && loaderConfig.has['dojo-undef-api']) {
381✔
107
                        buf.push("req.undef = " +  Template.getFunctionContent(runtime.undef));
36✔
108
                }
109
                buf.push(`var absMidsWaiting = globalObj[${chunkLoadingGlobal}].absMidsWaiting;`);
381✔
110
                buf.push("if (absMidsWaiting) {");
381✔
111
                buf.push("   absMidsWaiting.forEach(registerAbsMids);");
381✔
112
                buf.push(`   delete globalObj[${chunkLoadingGlobal}].absMidsWaiting;`);
381✔
113
                buf.push("}");
381✔
114
                return Template.asString([
381✔
115
                        `(function() { /* Start ${pluginName} extensions */`,
116
                        Template.indent(buf),
117
                        `})(); /* End ${pluginName} extensions */`
118
                ]);
119
        }
120

121
        getDojoLoaderModule() {
122
                const result = Array.from(this.compilation.modules).find((module) => {
388✔
123
                        return module.rawRequest === this.pluginProps.embeddedLoaderFilename;
2,296✔
124
                });
125
                if (!result) {
388✔
126
                         const error = new Error("Can't locate " + this.pluginProps.embeddedLoaderFilename + " in compilation");
1✔
127
                         this.addError(error);
1✔
128
                         throw error;
1✔
129
                }
130
                return result;
387✔
131
        }
132
        renderDojoConfigVars(loaderScope) {
133
                // Defines and assigns the defalutConfig and userConfig vars on the client.
134
                // If loaderScope is defined, then the embedded Dojo loader does not include the config API and so
135
                // the post-processed properties exported in the loaderScope should be used to specify the default config
136
                var defaultConfig = {hasCache:this.getDefaultFeatures()};
381✔
137
                const buf = [];
381✔
138
                const chunkGraph = this.chunkGraph || this.compilation.chunkGraph;
381!
139
                // loader config props duplicated in default config when not using config api
140
                if (util.isString(this.options.loaderConfig)) {
381✔
141
                        const dojoLoaderConfig = Array.from(this.compilation.modules).find((module) => { return module.rawRequest === this.options.loaderConfig;});
123✔
142
                        var id = chunkGraph.getModuleId(dojoLoaderConfig);
36✔
143
                        buf.push(`var userConfig = __webpack_require__(${JSON.stringify(id)});`);
36✔
144
                        buf.push(`if (typeof userConfig === 'function') {`);
36✔
145
                        buf.push(Template.indent(`userConfig = userConfig.call(globalObj, ${stringify(this.options.environment || {})});`));
36✔
146
                        buf.push("}");
36✔
147
                } else {
148
                        var loaderConfig = this.options.loaderConfig;
345✔
149
                        if (typeof loaderConfig === 'function') {
345✔
150
                                loaderConfig = loaderConfig(this.options.environment || {});
33✔
151
                        }
152
                        if (loaderScope) {
345✔
153
                                // make a working copy of the config for us to modify
154
                                loaderConfig = Object.assign({}, loaderConfig);
21✔
155

156
                                // Items to copy from the require object to the default config
157
                                ["paths", "pathsMapProg", "packs", "aliases", "mapProgs",  "cacheBust"].forEach(prop => {
21✔
158
                                        defaultConfig[prop] = loaderScope.require[prop];
126✔
159
                                });
160
                                ["modules", "cache"].forEach(prop => {
21✔
161
                                        defaultConfig[prop] = {};
42✔
162
                                });
163
                                // Remove packages defined by the loader default config
164
                                ["dojo", "dijit", "dojox", "tests", "doh", "build", "demos"].forEach(prop => {
21✔
165
                                        if (!loaderConfig.packages || !loaderConfig.packages.find(pack => {return pack.name === prop;})) delete defaultConfig.packs[prop];
147✔
166
                                });
167
                                // Remove duplicated/redundant items from the user config since they are not needed by Dojo.
168
                                ["paths", "packages", "aliases", "maps", "cacheBust"].forEach(prop => {
21✔
169
                                        delete loaderConfig[prop];
105✔
170
                                });
171
                                defaultConfig.hasCache = this.getDefaultFeatures();
21✔
172
                        }
173
                        buf.push(`var userConfig = mix(globalObj.dojoConfig, ${stringify(loaderConfig)});`);
345✔
174
                }
175
                buf.push(`var defaultConfig = ${stringify(defaultConfig)};`);
381✔
176
                return Template.asString(buf);
381✔
177
        }
178

179
        getDefaultFeatures() {
180
                return require("./defaultFeatures");
402✔
181
        }
182

183
};
184
module.exports = DojoAMDRuntimeModule;
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc