Skip to content

Commit f7d19b5

Browse files
committed
Add 'tslib.umd.js' to avoid global pollution
1 parent 2c3d5d6 commit f7d19b5

10 files changed

+1010
-9
lines changed

.npmignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
src
2+
scripts

CopyrightNotice.txt

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
/*! *****************************************************************************
2-
Copyright (c) Microsoft Corporation. All rights reserved.
2+
Copyright (c) Microsoft Corporation. All rights reserved.
33
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
44
this file except in compliance with the License. You may obtain a copy of the
5-
License at http://www.apache.org/licenses/LICENSE-2.0
6-
5+
License at http://www.apache.org/licenses/LICENSE-2.0
6+
77
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
88
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
9-
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10-
MERCHANTABLITY OR NON-INFRINGEMENT.
11-
9+
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10+
MERCHANTABLITY OR NON-INFRINGEMENT.
11+
1212
See the Apache Version 2.0 License for specific language governing permissions
1313
and limitations under the License.
1414
***************************************************************************** */
15-

package-lock.json

+20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+10-2
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,23 @@
1414
"tslib",
1515
"runtime"
1616
],
17+
"scripts": {
18+
"build-generator": "tsc scripts/generator.ts --module commonjs --target es2015",
19+
"build": "npm run build-generator && node scripts/generator.js src ."
20+
},
1721
"bugs": {
1822
"url": "https://github.com/Microsoft/TypeScript/issues"
1923
},
2024
"repository": {
2125
"type": "git",
2226
"url": "https://github.com/Microsoft/tslib.git"
2327
},
24-
"main": "tslib.js",
28+
"main": "tslib.umd.js",
2529
"module": "tslib.es6.js",
2630
"jsnext:main": "tslib.es6.js",
27-
"typings": "tslib.d.ts"
31+
"typings": "tslib.d.ts",
32+
"devDependencies": {
33+
"@types/node": "^6.0.110",
34+
"typescript": "^2.9.0-dev.20180512"
35+
}
2836
}

scripts/generator.js

+257
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });
3+
const fs = require("fs");
4+
const path = require("path");
5+
const ts = require("typescript");
6+
const rootDir = path.resolve(__dirname, `..`);
7+
const srcDir = path.resolve(rootDir, `src`);
8+
const copyrightNotice = fs.readFileSync(path.resolve(rootDir, "CopyrightNotice.txt"), "utf8");
9+
const umdGlobalsExporter = fs.readFileSync(path.resolve(srcDir, "umdGlobals.js"), "utf8");
10+
const umdExporter = fs.readFileSync(path.resolve(srcDir, "umd.js"), "utf8");
11+
const tslibFile = path.resolve(srcDir, "tslib.js");
12+
const indentStrings = ["", " "];
13+
const MAX_SMI_X86 = 1073741823;
14+
class TextWriter {
15+
constructor() {
16+
this.indent = 0;
17+
this.output = "";
18+
this.pendingNewLines = 0;
19+
}
20+
write(s) {
21+
if (s && s.length) {
22+
this.writePendingNewLines();
23+
this.output += s;
24+
}
25+
}
26+
writeLine(s) {
27+
this.write(s);
28+
this.pendingNewLines++;
29+
}
30+
writeLines(s) {
31+
if (s) {
32+
const lines = s.split(/\r\n?|\n/g);
33+
const indentation = guessIndentation(lines);
34+
for (const lineText of lines) {
35+
const line = indentation ? lineText.slice(indentation) : lineText;
36+
if (!this.pendingNewLines && this.output.length > 0) {
37+
this.writeLine();
38+
}
39+
this.writeLine(line);
40+
}
41+
}
42+
}
43+
toString() {
44+
return this.output;
45+
}
46+
writePendingNewLines() {
47+
if (this.pendingNewLines > 0) {
48+
do {
49+
this.output += "\n";
50+
this.pendingNewLines--;
51+
} while (this.pendingNewLines > 0);
52+
this.output += getIndentString(this.indent);
53+
}
54+
}
55+
}
56+
main();
57+
function main() {
58+
const sourceFiles = parseSources();
59+
generateSingleFileVariations(sourceFiles, rootDir);
60+
}
61+
function getIndentString(level) {
62+
if (indentStrings[level] === undefined) {
63+
indentStrings[level] = getIndentString(level - 1) + indentStrings[1];
64+
}
65+
return indentStrings[level];
66+
}
67+
function guessIndentation(lines) {
68+
let indentation = MAX_SMI_X86;
69+
for (const line of lines) {
70+
if (!line.length) {
71+
continue;
72+
}
73+
let i = 0;
74+
for (; i < line.length && i < indentation; i++) {
75+
if (!/^[\s\r\n]/.test(line.charAt(i))) {
76+
break;
77+
}
78+
}
79+
if (i < indentation) {
80+
indentation = i;
81+
}
82+
if (indentation === 0) {
83+
return 0;
84+
}
85+
}
86+
return indentation === MAX_SMI_X86 ? undefined : indentation;
87+
}
88+
function mkdirpSync(dir) {
89+
try {
90+
fs.mkdirSync(dir);
91+
}
92+
catch (e) {
93+
if (e.code === "EEXIST")
94+
return;
95+
if (e.code === "ENOENT") {
96+
const parent = path.dirname(dir);
97+
if (parent && parent !== dir) {
98+
mkdirpSync(parent);
99+
fs.mkdirSync(dir);
100+
return;
101+
}
102+
}
103+
throw e;
104+
}
105+
}
106+
function parse(file) {
107+
const sourceText = fs.readFileSync(file, "utf8");
108+
const sourceFile = ts.createSourceFile(file, sourceText, ts.ScriptTarget.ES3, /*setParentNodes*/ true, ts.ScriptKind.JS);
109+
return sourceFile;
110+
}
111+
function parseSources() {
112+
const sourceFiles = [];
113+
sourceFiles.push(parse(tslibFile));
114+
return sourceFiles;
115+
}
116+
function generateSingleFileVariations(sourceFiles, outDir) {
117+
generateSingleFile(sourceFiles, path.resolve(outDir, "tslib.js"), 1 /* UmdGlobal */);
118+
generateSingleFile(sourceFiles, path.resolve(outDir, "tslib.umd.js"), 0 /* Umd */);
119+
generateSingleFile(sourceFiles, path.resolve(outDir, "tslib.es6.js"), 2 /* ES2015 */);
120+
}
121+
function generateSingleFile(sourceFiles, outFile, libKind) {
122+
const bundle = ts.createBundle(sourceFiles);
123+
const output = write(bundle, libKind);
124+
mkdirpSync(path.dirname(outFile));
125+
fs.writeFileSync(outFile, output, "utf8");
126+
}
127+
function formatMessage(node, message) {
128+
const sourceFile = node.getSourceFile();
129+
if (sourceFile) {
130+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
131+
return `${sourceFile.fileName}(${line + 1}, ${character + 1}): ${message}`;
132+
}
133+
return message;
134+
}
135+
function reportError(node, message) {
136+
console.error(formatMessage(node, message));
137+
}
138+
function write(source, libKind) {
139+
const globalWriter = new TextWriter();
140+
const bodyWriter = new TextWriter();
141+
const exportWriter = new TextWriter();
142+
let sourceFile;
143+
return writeBundle(source);
144+
function writeBundle(node) {
145+
switch (libKind) {
146+
case 0 /* Umd */:
147+
case 1 /* UmdGlobal */:
148+
return writeUmdBundle(node);
149+
case 2 /* ES2015 */:
150+
return writeES2015Bundle(node);
151+
}
152+
}
153+
function writeUmdBundle(node) {
154+
visit(node);
155+
const writer = new TextWriter();
156+
writer.writeLines(copyrightNotice);
157+
writer.writeLines(globalWriter.toString());
158+
writer.writeLines(libKind === 1 /* UmdGlobal */ ? umdGlobalsExporter : umdExporter);
159+
writer.writeLine(`(function (exporter) {`);
160+
writer.indent++;
161+
writer.writeLines(bodyWriter.toString());
162+
writer.writeLine();
163+
writer.writeLines(exportWriter.toString());
164+
writer.indent--;
165+
writer.writeLine(`});`);
166+
return writer.toString();
167+
}
168+
function writeES2015Bundle(node) {
169+
visit(node);
170+
const writer = new TextWriter();
171+
writer.writeLines(copyrightNotice);
172+
writer.writeLines(bodyWriter.toString());
173+
return writer.toString();
174+
}
175+
function visit(node) {
176+
switch (node.kind) {
177+
case ts.SyntaxKind.Bundle: return visitBundle(node);
178+
case ts.SyntaxKind.SourceFile: return visitSourceFile(node);
179+
case ts.SyntaxKind.VariableStatement: return visitVariableStatement(node);
180+
case ts.SyntaxKind.FunctionDeclaration: return visitFunctionDeclaration(node);
181+
default:
182+
reportError(node, `${ts.SyntaxKind[node.kind]} not supported at the top level.`);
183+
return undefined;
184+
}
185+
}
186+
function visitBundle(node) {
187+
node.sourceFiles.forEach(visit);
188+
}
189+
function visitSourceFile(node) {
190+
sourceFile = node;
191+
node.statements.forEach(visit);
192+
}
193+
function visitFunctionDeclaration(node) {
194+
if (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) {
195+
if (libKind === 0 /* Umd */ || libKind === 1 /* UmdGlobal */) {
196+
exportWriter.writeLine(`exporter("${ts.idText(node.name)}", ${ts.idText(node.name)});`);
197+
const parametersText = sourceFile.text.slice(node.parameters.pos, node.parameters.end);
198+
const bodyText = node.body.getText();
199+
if (libKind === 1 /* UmdGlobal */) {
200+
globalWriter.writeLine(`var ${ts.idText(node.name)};`);
201+
bodyWriter.writeLines(`${ts.idText(node.name)} = function (${parametersText}) ${bodyText};`);
202+
}
203+
else {
204+
bodyWriter.writeLines(`function ${ts.idText(node.name)}(${parametersText}) ${bodyText}`);
205+
}
206+
bodyWriter.writeLine();
207+
return;
208+
}
209+
}
210+
bodyWriter.writeLines(node.getText());
211+
bodyWriter.writeLine();
212+
}
213+
function visitVariableStatement(node) {
214+
if (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) {
215+
if (node.declarationList.declarations.length > 1) {
216+
reportError(node, `Only single variables are supported on exported variable statements.`);
217+
return;
218+
}
219+
const variable = node.declarationList.declarations[0];
220+
if (variable.name.kind !== ts.SyntaxKind.Identifier) {
221+
reportError(variable.name, `Only identifier names are supported on exported variable statements.`);
222+
return;
223+
}
224+
if (!variable.initializer) {
225+
reportError(variable.name, `Exported variables must have an initializer.`);
226+
return;
227+
}
228+
if (libKind === 0 /* Umd */ || libKind === 1 /* UmdGlobal */) {
229+
if (libKind === 1 /* UmdGlobal */) {
230+
globalWriter.writeLine(`var ${ts.idText(variable.name)};`);
231+
bodyWriter.writeLines(`${ts.idText(variable.name)} = ${variable.initializer.getText()};`);
232+
}
233+
else if (ts.isFunctionExpression(variable.initializer)) {
234+
const parametersText = sourceFile.text.slice(variable.initializer.parameters.pos, variable.initializer.parameters.end);
235+
const bodyText = variable.initializer.body.getText();
236+
bodyWriter.writeLines(`function ${ts.idText(variable.name)}(${parametersText}) ${bodyText}`);
237+
bodyWriter.writeLine();
238+
}
239+
else {
240+
bodyWriter.writeLines(`var ${ts.idText(variable.name)} = ${variable.initializer.getText()};`);
241+
}
242+
bodyWriter.writeLine();
243+
exportWriter.writeLine(`exporter("${ts.idText(variable.name)}", ${ts.idText(variable.name)});`);
244+
return;
245+
}
246+
if (ts.isFunctionExpression(variable.initializer)) {
247+
const parametersText = sourceFile.text.slice(variable.initializer.parameters.pos, variable.initializer.parameters.end);
248+
const bodyText = variable.initializer.body.getText();
249+
bodyWriter.writeLines(`export function ${ts.idText(variable.name)}(${parametersText}) ${bodyText}`);
250+
bodyWriter.writeLine();
251+
return;
252+
}
253+
}
254+
bodyWriter.writeLines(node.getText());
255+
bodyWriter.writeLine();
256+
}
257+
}

0 commit comments

Comments
 (0)