Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions internal/core/compileroptions.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package core

import (
"reflect"
"strings"

"github.com/microsoft/typescript-go/internal/collections"
Expand All @@ -11,6 +12,8 @@ import (
//go:generate go tool mvdan.cc/gofumpt -lang=go1.24 -w compileroptions_stringer_generated.go

type CompilerOptions struct {
_ noCopy

AllowJs Tristate `json:"allowJs,omitzero"`
AllowArbitraryExtensions Tristate `json:"allowArbitraryExtensions,omitzero"`
AllowSyntheticDefaultImports Tristate `json:"allowSyntheticDefaultImports,omitzero"`
Expand Down Expand Up @@ -145,6 +148,36 @@ type CompilerOptions struct {
Quiet Tristate `json:"quiet,omitzero"`
}

// noCopy may be embedded into structs which must not be copied
// after the first use.
//
// See https://golang.org/issues/8005#issuecomment-190753527
// for details.
type noCopy struct{}

// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock() {}
func (*noCopy) Unlock() {}

var optionsType = reflect.TypeFor[CompilerOptions]()

// Clone creates a shallow copy of the CompilerOptions.
func (options *CompilerOptions) Clone() *CompilerOptions {
// TODO: this could be generated code instead of reflection.
target := &CompilerOptions{}

sourceValue := reflect.ValueOf(options).Elem()
targetValue := reflect.ValueOf(target).Elem()

for i := range sourceValue.NumField() {
if optionsType.Field(i).IsExported() {
targetValue.Field(i).Set(sourceValue.Field(i))
}
}

return target
}

func (options *CompilerOptions) GetEmitScriptTarget() ScriptTarget {
if options.Target != ScriptTargetNone {
return options.Target
Expand Down
17 changes: 10 additions & 7 deletions internal/testutil/harnessutil/harnessutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,12 @@ func CompileFiles(
currentDirectory string,
symlinks map[string]string,
) *CompilationResult {
var compilerOptions core.CompilerOptions
var compilerOptions *core.CompilerOptions
if tsconfig != nil {
compilerOptions = *tsconfig.ParsedConfig.CompilerOptions
compilerOptions = tsconfig.ParsedConfig.CompilerOptions.Clone()
}
if compilerOptions == nil {
compilerOptions = &core.CompilerOptions{}
}
// Set default options for tests
if compilerOptions.NewLine == core.NewLineKindNone {
Expand All @@ -100,10 +103,10 @@ func CompileFiles(

// Parse harness and compiler options from the test configuration
if testConfig != nil {
setOptionsFromTestConfig(t, testConfig, &compilerOptions, &harnessOptions)
setOptionsFromTestConfig(t, testConfig, compilerOptions, &harnessOptions)
}

return CompileFilesEx(t, inputFiles, otherFiles, &harnessOptions, &compilerOptions, currentDirectory, symlinks, tsconfig)
return CompileFilesEx(t, inputFiles, otherFiles, &harnessOptions, compilerOptions, currentDirectory, symlinks, tsconfig)
}

func CompileFilesEx(
Expand Down Expand Up @@ -225,9 +228,9 @@ func CompileFilesEx(
result.Symlinks = symlinks
result.Repeat = func(testConfig TestConfiguration) *CompilationResult {
newHarnessOptions := *harnessOptions
newCompilerOptions := *compilerOptions
setOptionsFromTestConfig(t, testConfig, &newCompilerOptions, &newHarnessOptions)
return CompileFilesEx(t, inputFiles, otherFiles, &newHarnessOptions, &newCompilerOptions, currentDirectory, symlinks, tsconfig)
newCompilerOptions := compilerOptions.Clone()
setOptionsFromTestConfig(t, testConfig, newCompilerOptions, &newHarnessOptions)
return CompileFilesEx(t, inputFiles, otherFiles, &newHarnessOptions, newCompilerOptions, currentDirectory, symlinks, tsconfig)
}
return result
}
Expand Down
28 changes: 16 additions & 12 deletions internal/transformers/commonjsmodule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestCommonJSModuleTransformer(t *testing.T) {
output string
other string
jsx bool
options core.CompilerOptions
options *core.CompilerOptions
}{
// ImportDeclaration
{
Expand Down Expand Up @@ -100,7 +100,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
const a = __importStar(require("other"));`,
options: core.CompilerOptions{ESModuleInterop: core.TSTrue},
options: &core.CompilerOptions{ESModuleInterop: core.TSTrue},
},
{
title: "ImportDeclaration#8",
Expand All @@ -109,7 +109,7 @@ const a = __importStar(require("other"));`,
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const a = tslib_1.__importStar(require("other"));`,
options: core.CompilerOptions{ESModuleInterop: core.TSTrue, ImportHelpers: core.TSTrue},
options: &core.CompilerOptions{ESModuleInterop: core.TSTrue, ImportHelpers: core.TSTrue},
},

// ImportEqualsDeclaration
Expand Down Expand Up @@ -175,7 +175,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.a = void 0;
const tslib_1 = require("tslib");
exports.a = tslib_1.__importStar(require("other"));`,
options: core.CompilerOptions{ESModuleInterop: core.TSTrue, ImportHelpers: core.TSTrue},
options: &core.CompilerOptions{ESModuleInterop: core.TSTrue, ImportHelpers: core.TSTrue},
},
{
title: "ExportDeclaration#5",
Expand All @@ -184,7 +184,7 @@ exports.a = tslib_1.__importStar(require("other"));`,
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("other"), exports);`,
options: core.CompilerOptions{ESModuleInterop: core.TSTrue, ImportHelpers: core.TSTrue},
options: &core.CompilerOptions{ESModuleInterop: core.TSTrue, ImportHelpers: core.TSTrue},
},

// ExportAssignment
Expand Down Expand Up @@ -855,7 +855,7 @@ import("./other.ts");`,
output: `"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
Promise.resolve().then(() => require("./other.js"));`,
options: core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
options: &core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
},
{
title: "CallExpression#4",
Expand All @@ -872,7 +872,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
};
Object.defineProperty(exports, "__esModule", { value: true });
Promise.resolve(` + "`" + `${__rewriteRelativeImportExtension(x)}` + "`" + `).then(s => require(s));`,
options: core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
options: &core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
},
{
title: "CallExpression#5",
Expand All @@ -889,7 +889,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
};
Object.defineProperty(exports, "__esModule", { value: true });
Promise.resolve(` + "`" + `${__rewriteRelativeImportExtension(x, true)}` + "`" + `).then(s => require(s));`,
options: core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue, Jsx: core.JsxEmitPreserve},
options: &core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue, Jsx: core.JsxEmitPreserve},
},
{
title: "CallExpression#6",
Expand All @@ -899,7 +899,7 @@ import(x);`,
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
Promise.resolve(` + "`" + `${tslib_1.__rewriteRelativeImportExtension(x)}` + "`" + `).then(s => require(s));`,
options: core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue, ImportHelpers: core.TSTrue},
options: &core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue, ImportHelpers: core.TSTrue},
},
{
title: "CallExpression#7",
Expand Down Expand Up @@ -1016,6 +1016,10 @@ exports.a = a;`,
t.Parallel()

compilerOptions := rec.options
if compilerOptions == nil {
compilerOptions = &core.CompilerOptions{}
}

compilerOptions.Module = core.ModuleKindCommonJS
sourceFileAffecting := compilerOptions.SourceFileAffecting()

Expand All @@ -1031,10 +1035,10 @@ exports.a = a;`,
}

emitContext := printer.NewEmitContext()
resolver := binder.NewReferenceResolver(&compilerOptions, binder.ReferenceResolverHooks{})
resolver := binder.NewReferenceResolver(compilerOptions, binder.ReferenceResolverHooks{})

file = NewRuntimeSyntaxTransformer(emitContext, &compilerOptions, resolver).TransformSourceFile(file)
file = NewCommonJSModuleTransformer(emitContext, &compilerOptions, resolver, fakeGetEmitModuleFormatOfFile).TransformSourceFile(file)
file = NewRuntimeSyntaxTransformer(emitContext, compilerOptions, resolver).TransformSourceFile(file)
file = NewCommonJSModuleTransformer(emitContext, compilerOptions, resolver, fakeGetEmitModuleFormatOfFile).TransformSourceFile(file)
emittestutil.CheckEmit(t, emitContext, file, rec.output)
})
}
Expand Down
44 changes: 24 additions & 20 deletions internal/transformers/esmodule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestESModuleTransformer(t *testing.T) {
output string
other string
jsx bool
options core.CompilerOptions
options *core.CompilerOptions
}{
// ImportDeclaration
{
Expand All @@ -31,19 +31,19 @@ func TestESModuleTransformer(t *testing.T) {
title: "ImportDeclaration#2",
input: `import "./other.ts"`,
output: `import "./other.js";`,
options: core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
options: &core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
},
{
title: "ImportDeclaration#3",
input: `import "./other.tsx"`,
output: `import "./other.js";`,
options: core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
options: &core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
},
{
title: "ImportDeclaration#4",
input: `import "./other.tsx"`,
output: `import "./other.jsx";`,
options: core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue, Jsx: core.JsxEmitPreserve},
options: &core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue, Jsx: core.JsxEmitPreserve},
},

// ImportEqualsDeclaration
Expand All @@ -58,31 +58,31 @@ func TestESModuleTransformer(t *testing.T) {
output: `import { createRequire as _createRequire } from "module";
const __require = _createRequire(import.meta.url);
const x = __require("other");`,
options: core.CompilerOptions{Module: core.ModuleKindNode16},
options: &core.CompilerOptions{Module: core.ModuleKindNode16},
},
{
title: "ImportEqualsDeclaration#3",
input: `import x = require("./other.ts")`,
output: `import { createRequire as _createRequire } from "module";
const __require = _createRequire(import.meta.url);
const x = __require("./other.js");`,
options: core.CompilerOptions{Module: core.ModuleKindNode16, RewriteRelativeImportExtensions: core.TSTrue},
options: &core.CompilerOptions{Module: core.ModuleKindNode16, RewriteRelativeImportExtensions: core.TSTrue},
},
{
title: "ImportEqualsDeclaration#4",
input: `import x = require("./other.tsx")`,
output: `import { createRequire as _createRequire } from "module";
const __require = _createRequire(import.meta.url);
const x = __require("./other.js");`,
options: core.CompilerOptions{Module: core.ModuleKindNode16, RewriteRelativeImportExtensions: core.TSTrue},
options: &core.CompilerOptions{Module: core.ModuleKindNode16, RewriteRelativeImportExtensions: core.TSTrue},
},
{
title: "ImportEqualsDeclaration#5",
input: `import x = require("./other.tsx")`,
output: `import { createRequire as _createRequire } from "module";
const __require = _createRequire(import.meta.url);
const x = __require("./other.jsx");`,
options: core.CompilerOptions{Module: core.ModuleKindNode16, RewriteRelativeImportExtensions: core.TSTrue, Jsx: core.JsxEmitPreserve},
options: &core.CompilerOptions{Module: core.ModuleKindNode16, RewriteRelativeImportExtensions: core.TSTrue, Jsx: core.JsxEmitPreserve},
},
{
title: "ImportEqualsDeclaration#6",
Expand All @@ -91,7 +91,7 @@ const x = __require("./other.jsx");`,
const __require = _createRequire(import.meta.url);
const x = __require("other");
export { x };`,
options: core.CompilerOptions{Module: core.ModuleKindNode16},
options: &core.CompilerOptions{Module: core.ModuleKindNode16},
},

// ExportAssignment
Expand All @@ -104,7 +104,7 @@ export { x };`,
title: "ExportAssignment#2",
input: `export = x`,
output: `module.exports = x;`,
options: core.CompilerOptions{Module: core.ModuleKindPreserve},
options: &core.CompilerOptions{Module: core.ModuleKindPreserve},
},

// ExportDeclaration
Expand All @@ -117,13 +117,13 @@ export { x };`,
title: "ExportDeclaration#2",
input: `export * from "./other.ts";`,
output: `export * from "./other.js";`,
options: core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
options: &core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
},
{
title: "ExportDeclaration#3",
input: `export * as x from "other";`,
output: `export * as x from "other";`,
options: core.CompilerOptions{Module: core.ModuleKindESNext},
options: &core.CompilerOptions{Module: core.ModuleKindESNext},
},
{
title: "ExportDeclaration#4",
Expand Down Expand Up @@ -160,7 +160,7 @@ export default default_1;`,
import("./other.ts");`,
output: `export {};
import("./other.js");`,
options: core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
options: &core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
},
{
title: "CallExpression#4",
Expand All @@ -176,7 +176,7 @@ import(x);`,
};
export {};
import(__rewriteRelativeImportExtension(x));`,
options: core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
options: &core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue},
},
{
title: "CallExpression#5",
Expand All @@ -192,7 +192,7 @@ import(x);`,
};
export {};
import(__rewriteRelativeImportExtension(x, true));`,
options: core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue, Jsx: core.JsxEmitPreserve},
options: &core.CompilerOptions{RewriteRelativeImportExtensions: core.TSTrue, Jsx: core.JsxEmitPreserve},
},
{
title: "CallExpression#6",
Expand All @@ -201,7 +201,7 @@ import(x);`,
output: `import { __rewriteRelativeImportExtension } from "tslib";
export {};
import(__rewriteRelativeImportExtension(x));`,
options: core.CompilerOptions{Module: core.ModuleKindESNext, RewriteRelativeImportExtensions: core.TSTrue, ImportHelpers: core.TSTrue},
options: &core.CompilerOptions{Module: core.ModuleKindESNext, RewriteRelativeImportExtensions: core.TSTrue, ImportHelpers: core.TSTrue},
},
{
title: "CallExpression#7",
Expand All @@ -212,14 +212,18 @@ var __rewriteRelativeImportExtension;`,
export {};
import(__rewriteRelativeImportExtension_1(x));
var __rewriteRelativeImportExtension;`,
options: core.CompilerOptions{Module: core.ModuleKindESNext, RewriteRelativeImportExtensions: core.TSTrue, ImportHelpers: core.TSTrue},
options: &core.CompilerOptions{Module: core.ModuleKindESNext, RewriteRelativeImportExtensions: core.TSTrue, ImportHelpers: core.TSTrue},
},
}
for _, rec := range data {
t.Run(rec.title, func(t *testing.T) {
t.Parallel()

compilerOptions := rec.options
if compilerOptions == nil {
compilerOptions = &core.CompilerOptions{}
}

sourceFileAffecting := compilerOptions.SourceFileAffecting()
file := parsetestutil.ParseTypeScript(rec.input, rec.jsx)
parsetestutil.CheckDiagnostics(t, file)
Expand All @@ -233,10 +237,10 @@ var __rewriteRelativeImportExtension;`,
}

emitContext := printer.NewEmitContext()
resolver := binder.NewReferenceResolver(&compilerOptions, binder.ReferenceResolverHooks{})
resolver := binder.NewReferenceResolver(compilerOptions, binder.ReferenceResolverHooks{})

file = NewRuntimeSyntaxTransformer(emitContext, &compilerOptions, resolver).TransformSourceFile(file)
file = NewESModuleTransformer(emitContext, &compilerOptions, resolver, fakeGetEmitModuleFormatOfFile).TransformSourceFile(file)
file = NewRuntimeSyntaxTransformer(emitContext, compilerOptions, resolver).TransformSourceFile(file)
file = NewESModuleTransformer(emitContext, compilerOptions, resolver, fakeGetEmitModuleFormatOfFile).TransformSourceFile(file)
emittestutil.CheckEmit(t, emitContext, file, rec.output)
})
}
Expand Down
Loading