diff --git a/src/typescript-ast-nodes.js b/src/typescript-ast-nodes.js
index 0a29974c1..93651dc21 100644
--- a/src/typescript-ast-nodes.js
+++ b/src/typescript-ast-nodes.js
@@ -146,6 +146,12 @@ module.exports = function(fork) {
.field("expression", def("Literal"))
.bases("Declaration");
+ def("TSNamespaceFunctionDeclaration")
+ .build("id", "body")
+ .field("id", def("Identifier"))
+ .field("body", def("BlockStatement"))
+ .bases("Declaration");
+
def("TSInterfaceDeclaration")
.build("name", "members")
.field("name", def("Identifier"))
diff --git a/tests/typescript/compiler/__snapshots__/jsfmt.spec.js.snap b/tests/typescript/compiler/__snapshots__/jsfmt.spec.js.snap
index 0680b430b..9260bc3d8 100644
--- a/tests/typescript/compiler/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/typescript/compiler/__snapshots__/jsfmt.spec.js.snap
@@ -57,6 +57,19 @@ values = values2;
`;
+exports[`commentInNamespaceDeclarationWithIdentifierPathName.ts 1`] = `
+namespace hello.hi.world
+{
+ function foo() {}
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+namespace hello.hi.world {
+ function foo() {
+ }
+}
+
+`;
+
exports[`commentsInterface.ts 1`] = `
interface i2 {
foo: (/**param help*/b: number) => string;
diff --git a/tests/typescript/compiler/commentInNamespaceDeclarationWithIdentifierPathName.ts b/tests/typescript/compiler/commentInNamespaceDeclarationWithIdentifierPathName.ts
new file mode 100644
index 000000000..5b4dbffe0
--- /dev/null
+++ b/tests/typescript/compiler/commentInNamespaceDeclarationWithIdentifierPathName.ts
@@ -0,0 +1,4 @@
+namespace hello.hi.world
+{
+ function foo() {}
+}
diff --git a/tests/typescript/webhost/__snapshots__/jsfmt.spec.js.snap b/tests/typescript/webhost/__snapshots__/jsfmt.spec.js.snap
new file mode 100644
index 000000000..04f684ecf
--- /dev/null
+++ b/tests/typescript/webhost/__snapshots__/jsfmt.spec.js.snap
@@ -0,0 +1,218 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`webtsc.ts 1`] = `
+///
+
+namespace TypeScript.WebTsc {
+
+ declare var RealActiveXObject: { new (s: string): any };
+
+ function getWScriptSystem() {
+ const fso = new RealActiveXObject("Scripting.FileSystemObject");
+
+ const fileStream = new ActiveXObject("ADODB.Stream");
+ fileStream.Type = 2 /*text*/;
+
+ const args: string[] = [];
+ for (let i = 0; i < WScript.Arguments.length; i++) {
+ args[i] = WScript.Arguments.Item(i);
+ }
+ return {
+ args: args,
+ newLine: "\\r\\n",
+ write(s: string): void {
+ WScript.StdOut.Write(s);
+ },
+ writeErr(s: string): void {
+ WScript.StdErr.Write(s);
+ },
+ readFile(fileName: string, encoding?: string): string {
+ if (!fso.FileExists(fileName)) {
+ return undefined;
+ }
+ fileStream.Open();
+ try {
+ if (encoding) {
+ fileStream.Charset = encoding;
+ fileStream.LoadFromFile(fileName);
+ }
+ else {
+ // Load file and read the first two bytes into a string with no interpretation
+ fileStream.Charset = "x-ansi";
+ fileStream.LoadFromFile(fileName);
+ const bom = fileStream.ReadText(2) || "";
+ // Position must be at 0 before encoding can be changed
+ fileStream.Position = 0;
+ // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
+ fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8";
+ }
+ // ReadText method always strips byte order mark from resulting string
+ return fileStream.ReadText();
+ }
+ catch (e) {
+ throw e;
+ }
+ finally {
+ fileStream.Close();
+ }
+ },
+ writeFile(fileName: string, data: string): boolean {
+ const f = fso.CreateTextFile(fileName, true);
+ f.Write(data);
+ f.Close();
+ return true;
+ },
+ resolvePath(path: string): string {
+ return fso.GetAbsolutePathName(path);
+ },
+ fileExists(path: string): boolean {
+ return fso.FileExists(path);
+ },
+ directoryExists(path: string) {
+ return fso.FolderExists(path);
+ },
+ createDirectory(directoryName: string) {
+ if (!this.directoryExists(directoryName)) {
+ fso.CreateFolder(directoryName);
+ }
+ },
+ getExecutingFilePath() {
+ return WScript.ScriptFullName;
+ },
+ getCurrentDirectory() {
+ return "";
+ },
+ getMemoryUsage() {
+ return 0;
+ },
+ exit(exitCode?: number): void {
+ WScript.Quit(exitCode);
+ },
+ useCaseSensitiveFileNames: false
+ };
+ }
+
+ export function prepareCompiler(currentDir: string, stdOut: ITextWriter, stdErr: ITextWriter) {
+ const shell = new RealActiveXObject("WScript.Shell");
+ shell.CurrentDirectory = currentDir;
+ WScript.ScriptFullName = currentDir + "\\\\tc.js";
+ WScript.StdOut = stdOut;
+ WScript.StdErr = stdErr;
+ sys = getWScriptSystem();
+
+ return (commandLine: string) => {
+ ts.executeCommandLine(commandLine.split(" "));
+ };
+ }
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+
+namespace TypeScript /*text*/.WebTsc {
+// Load file and read the first two bytes into a string with no interpretation
+// Position must be at 0 before encoding can be changed
+// [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
+// ReadText method always strips byte order mark from resulting string
+ declare var RealActiveXObject: { new (s: string): any };
+
+ function getWScriptSystem() {
+ const fso = new RealActiveXObject("Scripting.FileSystemObject");
+
+ const fileStream = new ActiveXObject("ADODB.Stream");
+ fileStream.Type = 2;
+
+ const args: string[] = [];
+ for (let i = 0; i < WScript.Arguments.length; i++) {
+ args[i] = WScript.Arguments.Item(i);
+ }
+ return {
+ args: args,
+ newLine: "\\r\\n",
+ write(s: string): void {
+ WScript.StdOut.Write(s);
+ },
+ writeErr(s: string): void {
+ WScript.StdErr.Write(s);
+ },
+ readFile(fileName: string, encoding?: string): string {
+ if (!fso.FileExists(fileName)) {
+ return undefined;
+ }
+ fileStream.Open();
+ try {
+ if (encoding) {
+ fileStream.Charset = encoding;
+ fileStream.LoadFromFile(fileName);
+ } else {
+ fileStream.Charset = "x-ansi";
+ fileStream.LoadFromFile(fileName);
+ const bom = fileStream.ReadText(2) || "";
+ fileStream.Position = 0;
+ fileStream.Charset = bom.length >= 2 &&
+ ((bom.charCodeAt(0) === 0xff && bom.charCodeAt(1) === 0xfe) ||
+ (bom.charCodeAt(0) === 0xfe && bom.charCodeAt(1) === 0xff))
+ ? "unicode"
+ : "utf-8";
+ }
+ return fileStream.ReadText();
+ } catch (e) {
+ throw e;
+ } finally {
+ fileStream.Close();
+ }
+ },
+ writeFile(fileName: string, data: string): boolean {
+ const f = fso.CreateTextFile(fileName, true);
+ f.Write(data);
+ f.Close();
+ return true;
+ },
+ resolvePath(path: string): string {
+ return fso.GetAbsolutePathName(path);
+ },
+ fileExists(path: string): boolean {
+ return fso.FileExists(path);
+ },
+ directoryExists(path: string) {
+ return fso.FolderExists(path);
+ },
+ createDirectory(directoryName: string) {
+ if (!this.directoryExists(directoryName)) {
+ fso.CreateFolder(directoryName);
+ }
+ },
+ getExecutingFilePath() {
+ return WScript.ScriptFullName;
+ },
+ getCurrentDirectory() {
+ return "";
+ },
+ getMemoryUsage() {
+ return 0;
+ },
+ exit(exitCode?: number): void {
+ WScript.Quit(exitCode);
+ },
+ useCaseSensitiveFileNames: false
+ };
+ }
+
+ export function prepareCompiler(
+ currentDir: string,
+ stdOut: ITextWriter,
+ stdErr: ITextWriter
+ ) {
+ const shell = new RealActiveXObject("WScript.Shell");
+ shell.CurrentDirectory = currentDir;
+ WScript.ScriptFullName = currentDir + "\\\\tc.js";
+ WScript.StdOut = stdOut;
+ WScript.StdErr = stdErr;
+ sys = getWScriptSystem();
+
+ return (commandLine: string) => {
+ ts.executeCommandLine(commandLine.split(" "));
+ };
+ }
+}
+
+`;
diff --git a/tests/typescript/webhost/jsfmt.spec.js b/tests/typescript/webhost/jsfmt.spec.js
new file mode 100644
index 000000000..bc085c48c
--- /dev/null
+++ b/tests/typescript/webhost/jsfmt.spec.js
@@ -0,0 +1 @@
+run_spec(__dirname, { parser: "typescript" });
diff --git a/tests/typescript/webhost/webtsc.ts b/tests/typescript/webhost/webtsc.ts
new file mode 100644
index 000000000..3c682df62
--- /dev/null
+++ b/tests/typescript/webhost/webtsc.ts
@@ -0,0 +1,104 @@
+///
+
+namespace TypeScript.WebTsc {
+
+ declare var RealActiveXObject: { new (s: string): any };
+
+ function getWScriptSystem() {
+ const fso = new RealActiveXObject("Scripting.FileSystemObject");
+
+ const fileStream = new ActiveXObject("ADODB.Stream");
+ fileStream.Type = 2 /*text*/;
+
+ const args: string[] = [];
+ for (let i = 0; i < WScript.Arguments.length; i++) {
+ args[i] = WScript.Arguments.Item(i);
+ }
+ return {
+ args: args,
+ newLine: "\r\n",
+ write(s: string): void {
+ WScript.StdOut.Write(s);
+ },
+ writeErr(s: string): void {
+ WScript.StdErr.Write(s);
+ },
+ readFile(fileName: string, encoding?: string): string {
+ if (!fso.FileExists(fileName)) {
+ return undefined;
+ }
+ fileStream.Open();
+ try {
+ if (encoding) {
+ fileStream.Charset = encoding;
+ fileStream.LoadFromFile(fileName);
+ }
+ else {
+ // Load file and read the first two bytes into a string with no interpretation
+ fileStream.Charset = "x-ansi";
+ fileStream.LoadFromFile(fileName);
+ const bom = fileStream.ReadText(2) || "";
+ // Position must be at 0 before encoding can be changed
+ fileStream.Position = 0;
+ // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
+ fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8";
+ }
+ // ReadText method always strips byte order mark from resulting string
+ return fileStream.ReadText();
+ }
+ catch (e) {
+ throw e;
+ }
+ finally {
+ fileStream.Close();
+ }
+ },
+ writeFile(fileName: string, data: string): boolean {
+ const f = fso.CreateTextFile(fileName, true);
+ f.Write(data);
+ f.Close();
+ return true;
+ },
+ resolvePath(path: string): string {
+ return fso.GetAbsolutePathName(path);
+ },
+ fileExists(path: string): boolean {
+ return fso.FileExists(path);
+ },
+ directoryExists(path: string) {
+ return fso.FolderExists(path);
+ },
+ createDirectory(directoryName: string) {
+ if (!this.directoryExists(directoryName)) {
+ fso.CreateFolder(directoryName);
+ }
+ },
+ getExecutingFilePath() {
+ return WScript.ScriptFullName;
+ },
+ getCurrentDirectory() {
+ return "";
+ },
+ getMemoryUsage() {
+ return 0;
+ },
+ exit(exitCode?: number): void {
+ WScript.Quit(exitCode);
+ },
+ useCaseSensitiveFileNames: false
+ };
+ }
+
+ export function prepareCompiler(currentDir: string, stdOut: ITextWriter, stdErr: ITextWriter) {
+ const shell = new RealActiveXObject("WScript.Shell");
+ shell.CurrentDirectory = currentDir;
+ WScript.ScriptFullName = currentDir + "\\tc.js";
+ WScript.StdOut = stdOut;
+ WScript.StdErr = stdErr;
+ sys = getWScriptSystem();
+
+ return (commandLine: string) => {
+ ts.executeCommandLine(commandLine.split(" "));
+ };
+ }
+}