1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-24 08:09:08 -05:00

Improve globals for runtime type library

This commit is contained in:
Kitson Kelly 2018-10-22 16:08:14 +11:00 committed by Ryan Dahl
parent c4bddc4651
commit 64f0dfd50e
5 changed files with 53 additions and 72 deletions

View file

@ -1,19 +1,19 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license. // Copyright 2018 the Deno authors. All rights reserved. MIT license.
import * as blob from "./blob"; import * as blob from "./blob";
import * as console from "./console"; import * as console_ from "./console";
import * as fetch_ from "./fetch"; import * as fetch_ from "./fetch";
import { globalEval } from "./global_eval"; import { globalEval } from "./global_eval";
import { libdeno } from "./libdeno"; import { libdeno } from "./libdeno";
import * as textEncoding from "./text_encoding"; import * as textEncoding from "./text_encoding";
import * as timers from "./timers"; import * as timers from "./timers";
import * as urlsearchparams from "./url_search_params"; import * as urlSearchParams from "./url_search_params";
// During the build process, augmentations to the variable `window` in this // During the build process, augmentations to the variable `window` in this
// file are tracked and created as part of default library that is built into // file are tracked and created as part of default library that is built into
// deno, we only need to declare the enough to compile deno. // deno, we only need to declare the enough to compile deno.
declare global { declare global {
const console: console.Console; const console: console_.Console;
const setTimeout: typeof timers.setTimeout; const setTimeout: typeof timers.setTimeout;
// tslint:disable-next-line:variable-name // tslint:disable-next-line:variable-name
const TextEncoder: typeof textEncoding.TextEncoder; const TextEncoder: typeof textEncoding.TextEncoder;
@ -28,13 +28,13 @@ window.setInterval = timers.setInterval;
window.clearTimeout = timers.clearTimer; window.clearTimeout = timers.clearTimer;
window.clearInterval = timers.clearTimer; window.clearInterval = timers.clearTimer;
window.console = new console.Console(libdeno.print); window.console = new console_.Console(libdeno.print);
window.TextEncoder = textEncoding.TextEncoder; window.TextEncoder = textEncoding.TextEncoder;
window.TextDecoder = textEncoding.TextDecoder; window.TextDecoder = textEncoding.TextDecoder;
window.atob = textEncoding.atob; window.atob = textEncoding.atob;
window.btoa = textEncoding.btoa; window.btoa = textEncoding.btoa;
window.URLSearchParams = urlsearchparams.URLSearchParams; window.URLSearchParams = urlSearchParams.URLSearchParams;
window.fetch = fetch_.fetch; window.fetch = fetch_.fetch;

View file

@ -4,7 +4,7 @@
[WILDCARD]~~~~~~ [WILDCARD]~~~~~~
$asset$/lib.deno_runtime.d.tsILDCARD] $asset$/lib.deno_runtime.d.tsILDCARD]
[WILDCARD]const console: console.Console; [WILDCARD]declare const console: console_.Console;
[WILDCARD]~~~~~~~ [WILDCARD]~~~~~~~
[WILDCARD]'console' is declared here. [WILDCARD]'console' is declared here.

View file

@ -47,12 +47,14 @@ export function addVariableDeclaration(
node: StatementedNode, node: StatementedNode,
name: string, name: string,
type: string, type: string,
hasDeclareKeyword?: boolean,
jsdocs?: JSDoc[] jsdocs?: JSDoc[]
): VariableStatement { ): VariableStatement {
return node.addVariableStatement({ return node.addVariableStatement({
declarationKind: VariableDeclarationKind.Const, declarationKind: VariableDeclarationKind.Const,
declarations: [{ name, type }], declarations: [{ name, type }],
docs: jsdocs && jsdocs.map(jsdoc => jsdoc.getText()) docs: jsdocs && jsdocs.map(jsdoc => jsdoc.getText()),
hasDeclareKeyword
}); });
} }
@ -281,8 +283,17 @@ export function namespaceSourceFile(
} }
}); });
// TODO need to properly unwrap this
const globalNamespace = sourceFile.getNamespace("global"); const globalNamespace = sourceFile.getNamespace("global");
const globalNamespaceText = globalNamespace && globalNamespace.print(); let globalNamespaceText = "";
if (globalNamespace) {
const structure = globalNamespace.getStructure();
if (structure.bodyText && typeof structure.bodyText === "string") {
globalNamespaceText = structure.bodyText;
} else {
throw new TypeError("Unexpected global declaration structure.");
}
}
if (globalNamespace) { if (globalNamespace) {
globalNamespace.remove(); globalNamespace.remove();
} }
@ -319,7 +330,8 @@ export function namespaceSourceFile(
return `${output} return `${output}
${globalNamespaceText || ""} ${globalNamespaceText || ""}
namespace ${namespace} {
declare namespace ${namespace} {
${debug ? getSourceComment(sourceFile, rootPath) : ""} ${debug ? getSourceComment(sourceFile, rootPath) : ""}
${sourceFile.getText()} ${sourceFile.getText()}
}`; }`;

View file

@ -123,54 +123,36 @@ export function flatten({
namespace.addStatements(statements); namespace.addStatements(statements);
} }
interface MergeOptions { interface MergeGlobalOptions {
basePath: string; basePath: string;
declarationProject: Project;
debug?: boolean; debug?: boolean;
globalVarName: string; declarationProject: Project;
filePath: string; filePath: string;
globalVarName: string;
inputProject: Project; inputProject: Project;
interfaceName: string; interfaceName: string;
namespaceName: string;
targetSourceFile: SourceFile; targetSourceFile: SourceFile;
} }
/** Take a module and merge into into a single namespace */ /** Take a module and merge it into the global scope */
export function merge({ export function mergeGlobal({
basePath, basePath,
declarationProject,
debug, debug,
globalVarName, declarationProject,
filePath, filePath,
globalVarName,
inputProject, inputProject,
interfaceName, interfaceName,
namespaceName,
targetSourceFile targetSourceFile
}: MergeOptions) { }: MergeGlobalOptions): void {
// We have to build the module/namespace in small pieces which will reflect // Add the global object interface
// how the global runtime environment will be for Deno const interfaceDeclaration = targetSourceFile.addInterface({
name: interfaceName,
// We need to add a module named `"globals"` which will contain all the global hasDeclareKeyword: true
// runtime context
const mergedModule = targetSourceFile.addNamespace({
name: namespaceName,
hasDeclareKeyword: true,
declarationKind: NamespaceDeclarationKind.Module
});
// Add the global Window interface
const interfaceDeclaration = mergedModule.addInterface({
name: interfaceName
});
// Add the global scope augmentation module of the "globals" module
const mergedGlobalNamespace = mergedModule.addNamespace({
name: "global",
declarationKind: NamespaceDeclarationKind.Global
}); });
// Declare the global variable // Declare the global variable
addVariableDeclaration(mergedGlobalNamespace, globalVarName, interfaceName); addVariableDeclaration(targetSourceFile, globalVarName, interfaceName, true);
// Add self reference to the global variable // Add self reference to the global variable
addInterfaceProperty(interfaceDeclaration, globalVarName, interfaceName); addInterfaceProperty(interfaceDeclaration, globalVarName, interfaceName);
@ -201,9 +183,9 @@ export function merge({
TypeGuards.isPropertyAccessExpression(leftExpression) && TypeGuards.isPropertyAccessExpression(leftExpression) &&
leftExpression.getExpression().getText() === globalVarName leftExpression.getExpression().getText() === globalVarName
) { ) {
const windowProperty = leftExpression.getName(); const globalVarProperty = leftExpression.getName();
if (windowProperty !== globalVarName) { if (globalVarProperty !== globalVarName) {
globalVariables.set(windowProperty, { globalVariables.set(globalVarProperty, {
type: firstChild.getType(), type: firstChild.getType(),
node node
}); });
@ -228,7 +210,7 @@ export function merge({
dependentSourceFiles.add(valueDeclaration.getSourceFile()); dependentSourceFiles.add(valueDeclaration.getSourceFile());
} }
} }
addVariableDeclaration(mergedGlobalNamespace, property, type); addVariableDeclaration(targetSourceFile, property, type, true);
addInterfaceProperty(interfaceDeclaration, property, type); addInterfaceProperty(interfaceDeclaration, property, type);
} }
@ -255,7 +237,7 @@ export function merge({
const dtsSourceFile = declarationProject.getSourceFileOrThrow( const dtsSourceFile = declarationProject.getSourceFileOrThrow(
dtsFilePath dtsFilePath
); );
mergedModule.addStatements( targetSourceFile.addStatements(
namespaceSourceFile(dtsSourceFile, { namespaceSourceFile(dtsSourceFile, {
debug, debug,
namespace: declaration.getNamespaceImportOrThrow().getText(), namespace: declaration.getNamespaceImportOrThrow().getText(),
@ -267,7 +249,7 @@ export function merge({
} }
if (debug) { if (debug) {
addSourceComment(mergedModule, sourceFile, basePath); addSourceComment(targetSourceFile, sourceFile, basePath);
} }
} }
@ -413,20 +395,19 @@ export function main({
console.log(`Created module "deno".`); console.log(`Created module "deno".`);
} }
merge({ mergeGlobal({
basePath, basePath,
declarationProject,
debug, debug,
globalVarName: "window", declarationProject,
filePath: `${basePath}/js/globals.ts`, filePath: `${basePath}/js/globals.ts`,
globalVarName: "window",
inputProject, inputProject,
interfaceName: "Window", interfaceName: "Window",
namespaceName: `"globals"`,
targetSourceFile: libDTs targetSourceFile: libDTs
}); });
if (!silent) { if (!silent) {
console.log(`Created module "globals".`); console.log(`Merged "globals" into global scope.`);
} }
// Add the preamble // Add the preamble

View file

@ -4,7 +4,7 @@
import { Project, ts } from "ts-simple-ast"; import { Project, ts } from "ts-simple-ast";
import { assert, assertEqual, test } from "../../js/testing/testing"; import { assert, assertEqual, test } from "../../js/testing/testing";
import { flatten, merge } from "./build_library"; import { flatten, mergeGlobal } from "./build_library";
import { loadDtsFiles } from "./ast_util"; import { loadDtsFiles } from "./ast_util";
const { ModuleKind, ModuleResolutionKind, ScriptTarget } = ts; const { ModuleKind, ModuleResolutionKind, ScriptTarget } = ts;
@ -116,7 +116,7 @@ test(function buildLibraryMerge() {
outputSourceFile: targetSourceFile outputSourceFile: targetSourceFile
} = setupFixtures(); } = setupFixtures();
merge({ mergeGlobal({
basePath, basePath,
declarationProject, declarationProject,
debug, debug,
@ -124,31 +124,19 @@ test(function buildLibraryMerge() {
filePath: `${buildPath}/globals.ts`, filePath: `${buildPath}/globals.ts`,
inputProject, inputProject,
interfaceName: "FooBar", interfaceName: "FooBar",
namespaceName: `"bazqat"`,
targetSourceFile targetSourceFile
}); });
assert(targetSourceFile.getNamespace(`"bazqat"`) != null); assert(targetSourceFile.getNamespace("moduleC") != null);
assertEqual(targetSourceFile.getNamespaces().length, 1); assertEqual(targetSourceFile.getNamespaces().length, 1);
const namespaceBazqat = targetSourceFile.getNamespaceOrThrow(`"bazqat"`); assert(targetSourceFile.getInterface("FooBar") != null);
assert(namespaceBazqat.getNamespace("global") != null); assertEqual(targetSourceFile.getInterfaces().length, 1);
assert(namespaceBazqat.getNamespace("moduleC") != null); const variableDeclarations = targetSourceFile.getVariableDeclarations();
assertEqual(namespaceBazqat.getNamespaces().length, 2); assertEqual(variableDeclarations[0].getType().getText(), `FooBar`);
assert(namespaceBazqat.getInterface("FooBar") != null); assertEqual(variableDeclarations[1].getType().getText(), `moduleC.Bar`);
assertEqual(namespaceBazqat.getInterfaces().length, 1);
const globalNamespace = namespaceBazqat.getNamespaceOrThrow("global");
const variableDeclarations = globalNamespace.getVariableDeclarations();
assertEqual(
variableDeclarations[0].getType().getText(),
`import("bazqat").FooBar`
);
assertEqual(
variableDeclarations[1].getType().getText(),
`import("bazqat").moduleC.Bar`
);
assertEqual( assertEqual(
variableDeclarations[2].getType().getText(), variableDeclarations[2].getType().getText(),
`typeof import("bazqat").moduleC.qat` `typeof moduleC.qat`
); );
assertEqual(variableDeclarations.length, 3); assertEqual(variableDeclarations.length, 3);
}); });