@@ -4536,7 +4536,8 @@ void Parser::parse_and_visit_import(
45364536 bool possibly_typescript_import_alias = false ;
45374537 // For 'import fs from "node:fs";', declared_variable is 'fs'.
45384538 std::optional<Token> declared_variable = std::nullopt ;
4539- auto declare_variable_if_needed = [&](Variable_Kind kind) {
4539+ Variable_Kind declared_variable_kind = Variable_Kind::_import;
4540+ auto declare_variable_if_needed = [&]() {
45404541 if (declared_variable.has_value ()) {
45414542 switch (declared_variable->type ) {
45424543 // import var from "module"; // Invalid.
@@ -4552,7 +4553,7 @@ void Parser::parse_and_visit_import(
45524553 case Token_Type::kw_await:
45534554 case Token_Type::kw_yield:
45544555 case Token_Type::kw_let:
4555- if (kind == Variable_Kind::_import_alias) {
4556+ if (declared_variable_kind == Variable_Kind::_import_alias) {
45564557 // NOTE[TypeScript-namespace-alias-name]: TypeScript namespace aliases
45574558 // can be named 'await' because TypeScript namespace aliases do not
45584559 // enforce strict mode.
@@ -4578,7 +4579,8 @@ void Parser::parse_and_visit_import(
45784579 break ;
45794580 }
45804581
4581- v.visit_variable_declaration (declared_variable->identifier_name (), kind,
4582+ v.visit_variable_declaration (declared_variable->identifier_name (),
4583+ declared_variable_kind,
45824584 Variable_Declaration_Flags::none);
45834585 declared_variable = std::nullopt ; // Prevent double declaration.
45844586 }
@@ -4616,7 +4618,7 @@ void Parser::parse_and_visit_import(
46164618 declared_variable = this ->peek ();
46174619 this ->skip ();
46184620 if (this ->peek ().type == Token_Type::comma) {
4619- declare_variable_if_needed (Variable_Kind::_import );
4621+ declare_variable_if_needed ();
46204622 this ->skip ();
46214623 switch (this ->peek ().type ) {
46224624 // import fs, {readFile} from "fs";
@@ -4708,9 +4710,8 @@ void Parser::parse_and_visit_import(
47084710 case Token_Type::kw_type:
47094711 this ->lexer_ .commit_transaction (std::move (transaction));
47104712 report_type_only_import_in_javascript_if_needed ();
4711- v.visit_variable_declaration (this ->peek ().identifier_name (),
4712- Variable_Kind::_import_type,
4713- Variable_Declaration_Flags::none);
4713+ declared_variable = this ->peek ();
4714+ declared_variable_kind = Variable_Kind::_import_type;
47144715 this ->skip ();
47154716 if (this ->peek ().type == Token_Type::comma) {
47164717 this ->skip ();
@@ -4739,6 +4740,8 @@ void Parser::parse_and_visit_import(
47394740 QLJS_PARSER_UNIMPLEMENTED ();
47404741 break ;
47414742 }
4743+ } else {
4744+ possibly_typescript_import_alias = true ;
47424745 }
47434746 break ;
47444747
@@ -4772,12 +4775,12 @@ void Parser::parse_and_visit_import(
47724775
47734776 switch (this ->peek ().type ) {
47744777 case Token_Type::kw_from:
4775- declare_variable_if_needed (Variable_Kind::_import );
4778+ declare_variable_if_needed ();
47764779 this ->skip ();
47774780 break ;
47784781
47794782 case Token_Type::string:
4780- declare_variable_if_needed (Variable_Kind::_import );
4783+ declare_variable_if_needed ();
47814784 this ->diag_reporter_ ->report (Diag_Expected_From_Before_Module_Specifier{
47824785 .module_specifier = this ->peek ().span (),
47834786 });
@@ -4805,9 +4808,16 @@ void Parser::parse_and_visit_import(
48054808 if (this ->peek ().type == Token_Type::left_paren &&
48064809 namespace_name.normalized_name () == u8" require" _sv) {
48074810 // import fs = require("fs");
4811+ // import type fs = require("fs");
4812+
4813+ // NOTE[TypeScript-type-import-alias]: 'import fs = ' and
4814+ // 'import type fs = ...' both declare variables which conflict with
4815+ // 'let', 'class', etc. Overwrite Variable_Kind::_import_type.
4816+ //
48084817 // FIXME(strager): Should this behave like an import or an import
48094818 // alias or some other kind?
4810- declare_variable_if_needed (Variable_Kind::_import);
4819+ declared_variable_kind = Variable_Kind::_import;
4820+ declare_variable_if_needed ();
48114821 if (declare_context.declare_namespace_declare_keyword .has_value () &&
48124822 !declare_context.in_module ) {
48134823 this ->diag_reporter_ ->report (
@@ -4826,7 +4836,8 @@ void Parser::parse_and_visit_import(
48264836 } else {
48274837 // import myns = ns;
48284838 // import C = ns.C;
4829- declare_variable_if_needed (Variable_Kind::_import_alias);
4839+ declared_variable_kind = Variable_Kind::_import_alias;
4840+ declare_variable_if_needed ();
48304841 v.visit_variable_namespace_use (namespace_name);
48314842 while (this ->peek ().type == Token_Type::dot) {
48324843 this ->skip ();
@@ -4849,7 +4860,7 @@ void Parser::parse_and_visit_import(
48494860 }
48504861
48514862 default :
4852- declare_variable_if_needed (Variable_Kind::_import );
4863+ declare_variable_if_needed ();
48534864 QLJS_PARSER_UNIMPLEMENTED ();
48544865 break ;
48554866 }
@@ -4858,10 +4869,10 @@ void Parser::parse_and_visit_import(
48584869 return ;
48594870 }
48604871
4861- declare_variable_if_needed (Variable_Kind::_import );
4872+ declare_variable_if_needed ();
48624873 [[fallthrough]];
48634874 default :
4864- declare_variable_if_needed (Variable_Kind::_import );
4875+ declare_variable_if_needed ();
48654876 this ->diag_reporter_ ->report (Diag_Expected_From_And_Module_Specifier{
48664877 .where = Source_Code_Span::unit (this ->lexer_ .end_of_previous_token ()),
48674878 });
0 commit comments