]> git.proxmox.com Git - ceph.git/blob - ceph/src/arrow/js/gulp/closure-task.js
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / js / gulp / closure-task.js
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied. See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17
18 const {
19 targetDir,
20 mainExport,
21 esmRequire,
22 gCCLanguageNames,
23 publicModulePaths,
24 observableFromStreams,
25 shouldRunInChildProcess,
26 spawnGulpCommandInChildProcess,
27 } = require('./util');
28
29 const fs = require('fs');
30 const gulp = require('gulp');
31 const path = require('path');
32 const mkdirp = require('mkdirp');
33 const sourcemaps = require('gulp-sourcemaps');
34 const { memoizeTask } = require('./memoize-task');
35 const { compileBinFiles } = require('./typescript-task');
36 const closureCompiler = require('google-closure-compiler').gulp();
37
38 const closureTask = ((cache) => memoizeTask(cache, async function closure(target, format) {
39
40 if (shouldRunInChildProcess(target, format)) {
41 return spawnGulpCommandInChildProcess('compile', target, format);
42 }
43
44 const src = targetDir(target, `cls`);
45 const srcAbsolute = path.resolve(src);
46 const out = targetDir(target, format);
47 const externs = path.join(`${out}/${mainExport}.externs.js`);
48 const entry_point = path.join(`${src}/${mainExport}.dom.cls.js`);
49
50 const exportedImports = publicModulePaths(srcAbsolute).reduce((entries, publicModulePath) => [
51 ...entries, {
52 publicModulePath,
53 exports_: getPublicExportedNames(esmRequire(publicModulePath))
54 }
55 ], []);
56
57 await mkdirp(out);
58
59 await Promise.all([
60 fs.promises.writeFile(externs, generateExternsFile(exportedImports)),
61 fs.promises.writeFile(entry_point, generateUMDExportAssignment(srcAbsolute, exportedImports))
62 ]);
63
64 return await Promise.all([
65 runClosureCompileAsObservable().toPromise(),
66 compileBinFiles(target, format).toPromise()
67 ]);
68
69 function runClosureCompileAsObservable() {
70 return observableFromStreams(
71 gulp.src([
72 /* external libs first */
73 `node_modules/flatbuffers/package.json`,
74 `node_modules/flatbuffers/js/flatbuffers.mjs`,
75 `${src}/**/*.js` /* <-- then source globs */
76 ], { base: `./` }),
77 sourcemaps.init(),
78 closureCompiler(createClosureArgs(entry_point, externs, target), {
79 platform: ['native', 'java', 'javascript']
80 }),
81 // rename the sourcemaps from *.js.map files to *.min.js.map
82 sourcemaps.write(`.`, { mapFile: (mapPath) => mapPath.replace(`.js.map`, `.${target}.min.js.map`) }),
83 gulp.dest(out)
84 );
85 }
86 }))({});
87
88 module.exports = closureTask;
89 module.exports.closureTask = closureTask;
90
91 const createClosureArgs = (entry_point, externs, target) => ({
92 externs,
93 entry_point,
94 third_party: true,
95 warning_level: `QUIET`,
96 dependency_mode: `PRUNE`,
97 rewrite_polyfills: false,
98 module_resolution: `NODE`,
99 // formatting: `PRETTY_PRINT`,
100 // debug: true,
101 compilation_level: `ADVANCED`,
102 package_json_entry_names: `module,jsnext:main,main`,
103 assume_function_wrapper: true,
104 js_output_file: `${mainExport}.js`,
105 language_in: gCCLanguageNames[`esnext`],
106 language_out: gCCLanguageNames[target],
107 output_wrapper:`${apacheHeader()}
108 (function (global, factory) {
109 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
110 typeof define === 'function' && define.amd ? define(['exports'], factory) :
111 (factory(global.Arrow = global.Arrow || {}));
112 }(this, (function (exports) {%output%}.bind(this))));`
113 });
114
115 function generateUMDExportAssignment(src, exportedImports) {
116 return [
117 ...exportedImports.map(({ publicModulePath }, i) => {
118 const p = publicModulePath.slice(src.length + 1);
119 return (`import * as exports${i} from './${p}';`);
120 }).filter(Boolean),
121 'Object.assign(arguments[0], exports0);'
122 ].join('\n');
123 }
124
125 function generateExternsFile(exportedImports) {
126 return [
127 externsHeader(),
128 ...exportedImports.reduce((externBodies, { exports_ }) => [
129 ...externBodies, ...exports_.map(externBody)
130 ], []).filter(Boolean)
131 ].join('\n');
132 }
133
134 function externBody({ exportName, staticNames, instanceNames }) {
135 return [
136 `var ${exportName} = function() {};`,
137 staticNames.map((staticName) => (isNaN(+staticName)
138 ? `/** @type {?} */\n${exportName}.${staticName} = function() {};`
139 : `/** @type {?} */\n${exportName}[${staticName}] = function() {};`
140 )).join('\n'),
141 instanceNames.map((instanceName) => (isNaN(+instanceName)
142 ? `/** @type {?} */\n${exportName}.prototype.${instanceName};`
143 : `/** @type {?} */\n${exportName}.prototype[${instanceName}];`
144 )).join('\n')
145 ].filter(Boolean).join('\n');
146 }
147
148 function externsHeader() {
149 return (`${apacheHeader()}
150 // @ts-nocheck
151 /* eslint-disable */
152 /**
153 * @fileoverview Closure Compiler externs for Arrow
154 * @externs
155 * @suppress {duplicate,checkTypes}
156 */
157 /** @type {symbol} */
158 Symbol.iterator;
159 /** @type {symbol} */
160 Symbol.toPrimitive;
161 /** @type {symbol} */
162 Symbol.asyncIterator;
163 `);
164 }
165
166 function getPublicExportedNames(entryModule) {
167 const fn = function() {};
168 const isStaticOrProtoName = (x) => (
169 !(x in fn) &&
170 (x !== `default`) &&
171 (x !== `undefined`) &&
172 (x !== `__esModule`) &&
173 (x !== `constructor`) &&
174 !(x.startsWith('_'))
175 );
176 return Object
177 .getOwnPropertyNames(entryModule)
178 .filter((name) => name !== 'default')
179 .filter((name) => (
180 typeof entryModule[name] === `object` ||
181 typeof entryModule[name] === `function`
182 ))
183 .map((name) => [name, entryModule[name]])
184 .reduce((reserved, [name, value]) => {
185
186 const staticNames = value &&
187 typeof value === 'object' ? Object.getOwnPropertyNames(value).filter(isStaticOrProtoName) :
188 typeof value === 'function' ? Object.getOwnPropertyNames(value).filter(isStaticOrProtoName) : [];
189
190 const instanceNames = (typeof value === `function` && Object.getOwnPropertyNames(value.prototype || {}) || []).filter(isStaticOrProtoName);
191
192 return [...reserved, { exportName: name, staticNames, instanceNames }];
193 }, []);
194 }
195
196 function apacheHeader() {
197 return `// Licensed to the Apache Software Foundation (ASF) under one
198 // or more contributor license agreements. See the NOTICE file
199 // distributed with this work for additional information
200 // regarding copyright ownership. The ASF licenses this file
201 // to you under the Apache License, Version 2.0 (the
202 // "License"); you may not use this file except in compliance
203 // with the License. You may obtain a copy of the License at
204 //
205 // http://www.apache.org/licenses/LICENSE-2.0
206 //
207 // Unless required by applicable law or agreed to in writing,
208 // software distributed under the License is distributed on an
209 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
210 // KIND, either express or implied. See the License for the
211 // specific language governing permissions and limitations
212 // under the License.`;
213 }