aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--integration/bunjs-only-snippets/transpiler.test.js22
-rw-r--r--src/js_parser/js_parser.zig110
2 files changed, 112 insertions, 20 deletions
diff --git a/integration/bunjs-only-snippets/transpiler.test.js b/integration/bunjs-only-snippets/transpiler.test.js
index 310546e83..167032c9a 100644
--- a/integration/bunjs-only-snippets/transpiler.test.js
+++ b/integration/bunjs-only-snippets/transpiler.test.js
@@ -16,6 +16,18 @@ describe("Bun.Transpiler", () => {
const code = `import { useParams } from "remix";
import type { LoaderFunction, ActionFunction } from "remix";
+ import { type xx } from 'mod';
+ import { type xx as yy } from 'mod';
+ import { type 'xx' as yy } from 'mod';
+ import { type as } from 'mod';
+ import { type as as } from 'mod';
+ import { type as as as } from 'mod';
+ import { type xx } from 'mod';
+ import { type xx as yy } from 'mod';
+ import { type if as yy } from 'mod';
+ import { type 'xx' as yy } from 'mod';
+ import React, { type ReactNode } from 'react';
+
export const loader: LoaderFunction = async ({
params
@@ -40,6 +52,8 @@ describe("Bun.Transpiler", () => {
it("reports import paths, excluding types", () => {
const imports = transpiler.scanImports(code);
expect(imports.filter(({ path }) => path === "remix")).toHaveLength(1);
+ expect(imports.filter(({ path }) => path === "mod")).toHaveLength(0);
+ expect(imports.filter(({ path }) => path === "react")).toHaveLength(1);
});
});
@@ -123,12 +137,20 @@ describe("Bun.Transpiler", () => {
});
it("removes types", () => {
+ expect(code.includes("mod")).toBe(true);
+ expect(code.includes("xx")).toBe(true);
expect(code.includes("ActionFunction")).toBe(true);
expect(code.includes("LoaderFunction")).toBe(true);
+ expect(code.includes("ReactNode")).toBe(true);
+ expect(code.includes("React")).toBe(true);
const out = transpiler.transformSync(code);
expect(out.includes("ActionFunction")).toBe(false);
expect(out.includes("LoaderFunction")).toBe(false);
+ expect(out.includes("mod")).toBe(false);
+ expect(out.includes("xx")).toBe(false);
+ expect(out.includes("ReactNode")).toBe(false);
+ expect(out.includes("React")).toBe(true);
const { exports } = transpiler.scan(out);
expect(exports[0]).toBe("action");
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig
index 58e7f5a2a..6552a69e8 100644
--- a/src/js_parser/js_parser.zig
+++ b/src/js_parser/js_parser.zig
@@ -6896,28 +6896,98 @@ pub fn NewParser(
var original_name = alias;
try p.lexer.next();
- if (p.lexer.isContextualKeyword("as")) {
- try p.lexer.next();
- original_name = p.lexer.identifier;
- name = LocRef{ .loc = alias_loc, .ref = try p.storeNameInRef(original_name) };
- try p.lexer.expect(.t_identifier);
- } else if (!isIdentifier) {
- // An import where the name is a keyword must have an alias
- try p.lexer.expectedString("\"as\"");
- }
+ // "import { type xx } from 'mod'"
+ // "import { type xx as yy } from 'mod'"
+ // "import { type 'xx' as yy } from 'mod'"
+ // "import { type as } from 'mod'"
+ // "import { type as as } from 'mod'"
+ // "import { type as as as } from 'mod'"
+ if (is_typescript_enabled and
+ strings.eqlComptime(alias, "type") and
+ p.lexer.token != .t_comma and
+ p.lexer.token != .t_close_brace)
+ {
+ if (p.lexer.isContextualKeyword("as")) {
+ try p.lexer.next();
+ if (p.lexer.isContextualKeyword("as")) {
+ original_name = p.lexer.identifier;
+ name = LocRef{ .loc = p.lexer.loc(), .ref = try p.storeNameInRef(original_name) };
+ try p.lexer.next();
- // Reject forbidden names
- if (isEvalOrArguments(original_name)) {
- const r = js_lexer.rangeOfIdentifier(p.source, name.loc);
- try p.log.addRangeErrorFmt(p.source, r, p.allocator, "Cannot use \"{s}\" as an identifier here", .{original_name});
- }
+ if (p.lexer.token == .t_identifier) {
+ // "import { type as as as } from 'mod'"
+ // "import { type as as foo } from 'mod'"
+ try p.lexer.next();
+ } else {
+ // "import { type as as } from 'mod'"
+ try items.append(.{
+ .alias = alias,
+ .alias_loc = alias_loc,
+ .name = name,
+ .original_name = original_name,
+ });
+ }
+ } else if (p.lexer.token == .t_identifier) {
+ // "import { type as xxx } from 'mod'"
+ original_name = p.lexer.identifier;
+ name = LocRef{ .loc = p.lexer.loc(), .ref = try p.storeNameInRef(original_name) };
+ try p.lexer.expect(.t_identifier);
- try items.append(js_ast.ClauseItem{
- .alias = alias,
- .alias_loc = alias_loc,
- .name = name,
- .original_name = original_name,
- });
+ if (isEvalOrArguments(original_name)) {
+ const r = p.source.rangeOfString(name.loc);
+ try p.log.addRangeErrorFmt(p.source, r, p.allocator, "Cannot use {s} as an identifier here", .{original_name});
+ }
+
+ try items.append(.{
+ .alias = alias,
+ .alias_loc = alias_loc,
+ .name = name,
+ .original_name = original_name,
+ });
+ }
+ } else {
+ const is_identifier = p.lexer.token == .t_identifier;
+
+ // "import { type xx } from 'mod'"
+ // "import { type xx as yy } from 'mod'"
+ // "import { type if as yy } from 'mod'"
+ // "import { type 'xx' as yy } from 'mod'"
+ _ = try p.parseClauseAlias("import");
+ try p.lexer.next();
+
+ if (p.lexer.isContextualKeyword("as")) {
+ try p.lexer.next();
+
+ try p.lexer.expect(.t_identifier);
+ } else if (!is_identifier) {
+ // An import where the name is a keyword must have an alias
+ try p.lexer.expectedString("\"as\"");
+ }
+ }
+ } else {
+ if (p.lexer.isContextualKeyword("as")) {
+ try p.lexer.next();
+ original_name = p.lexer.identifier;
+ name = LocRef{ .loc = alias_loc, .ref = try p.storeNameInRef(original_name) };
+ try p.lexer.expect(.t_identifier);
+ } else if (!isIdentifier) {
+ // An import where the name is a keyword must have an alias
+ try p.lexer.expectedString("\"as\"");
+ }
+
+ // Reject forbidden names
+ if (isEvalOrArguments(original_name)) {
+ const r = js_lexer.rangeOfIdentifier(p.source, name.loc);
+ try p.log.addRangeErrorFmt(p.source, r, p.allocator, "Cannot use \"{s}\" as an identifier here", .{original_name});
+ }
+
+ try items.append(js_ast.ClauseItem{
+ .alias = alias,
+ .alias_loc = alias_loc,
+ .name = name,
+ .original_name = original_name,
+ });
+ }
if (p.lexer.token != .t_comma) {
break;