diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2c4999e516fd7..e43766d54569c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -60,7 +60,7 @@ namespace ts { const compilerOptions = host.getCompilerOptions(); const languageVersion = getEmitScriptTarget(compilerOptions); - const modulekind = getEmitModuleKind(compilerOptions); + const moduleKind = getEmitModuleKind(compilerOptions); const allowSyntheticDefaultImports = getAllowSyntheticDefaultImports(compilerOptions); const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks"); const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes"); @@ -443,6 +443,7 @@ namespace ts { let deferredGlobalAsyncIteratorType: GenericType; let deferredGlobalAsyncIterableIteratorType: GenericType; let deferredGlobalTemplateStringsArrayType: ObjectType; + let deferredGlobalImportMetaType: ObjectType; let deferredGlobalExtractSymbol: Symbol; let deferredNodes: Node[]; @@ -1094,7 +1095,7 @@ namespace ts { const declarationFile = getSourceFileOfNode(declaration); const useFile = getSourceFileOfNode(usage); if (declarationFile !== useFile) { - if ((modulekind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) || + if ((moduleKind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) || (!compilerOptions.outFile && !compilerOptions.out) || isInTypeQuery(usage) || declaration.flags & NodeFlags.Ambient) { @@ -7764,6 +7765,10 @@ namespace ts { return deferredGlobalTemplateStringsArrayType || (deferredGlobalTemplateStringsArrayType = getGlobalType("TemplateStringsArray" as __String, /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType; } + function getGlobalImportMetaType() { + return deferredGlobalImportMetaType || (deferredGlobalImportMetaType = getGlobalType("ImportMeta" as __String, /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType; + } + function getGlobalESSymbolConstructorSymbol(reportErrors: boolean) { return deferredGlobalESSymbolConstructorSymbol || (deferredGlobalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol" as __String, reportErrors)); } @@ -18780,6 +18785,17 @@ namespace ts { function checkMetaProperty(node: MetaProperty) { checkGrammarMetaProperty(node); + + if (node.keywordToken === SyntaxKind.NewKeyword) { + return checkNewTargetMetaProperty(node); + } + + if (node.keywordToken === SyntaxKind.ImportKeyword) { + return checkImportMetaProperty(node); + } + } + + function checkNewTargetMetaProperty(node: MetaProperty) { const container = getNewTargetContainer(node); if (!container) { error(node, Diagnostics.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, "new.target"); @@ -18795,6 +18811,16 @@ namespace ts { } } + function checkImportMetaProperty(node: MetaProperty) { + if (languageVersion < ScriptTarget.ESNext || moduleKind < ModuleKind.ESNext) { + error(node, Diagnostics.The_import_meta_meta_property_is_only_allowed_using_ESNext_for_the_target_and_module_compiler_options); + } + const file = getSourceFileOfNode(node); + Debug.assert(!!(file.flags & NodeFlags.PossiblyContainsImportMeta), "Containing file is missing import meta node flag."); + Debug.assert(!!file.externalModuleIndicator, "Containing file should be a module."); + return node.name.escapedText === "meta" ? getGlobalImportMetaType() : unknownType; + } + function getTypeOfParameter(symbol: Symbol) { const type = getTypeOfSymbol(symbol); if (strictNullChecks) { @@ -22417,7 +22443,7 @@ namespace ts { function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier) { // No need to check for require or exports for ES6 modules and later - if (modulekind >= ModuleKind.ES2015 || compilerOptions.noEmit) { + if (moduleKind >= ModuleKind.ES2015 || compilerOptions.noEmit) { return; } @@ -24613,7 +24639,7 @@ namespace ts { } } else { - if (modulekind >= ModuleKind.ES2015 && !(node.flags & NodeFlags.Ambient)) { + if (moduleKind >= ModuleKind.ES2015 && !(node.flags & NodeFlags.Ambient)) { // Import equals declaration is deprecated in es6 or above grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead); } @@ -24651,7 +24677,7 @@ namespace ts { error(node.moduleSpecifier, Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol)); } - if (modulekind !== ModuleKind.System && modulekind !== ModuleKind.ES2015 && modulekind !== ModuleKind.ESNext) { + if (moduleKind !== ModuleKind.System && moduleKind !== ModuleKind.ES2015 && moduleKind !== ModuleKind.ESNext) { checkExternalEmitHelpers(node, ExternalEmitHelpers.ExportStar); } } @@ -24724,11 +24750,11 @@ namespace ts { } if (node.isExportEquals && !(node.flags & NodeFlags.Ambient)) { - if (modulekind >= ModuleKind.ES2015) { + if (moduleKind >= ModuleKind.ES2015) { // export assignment is not supported in es6 modules grammarErrorOnNode(node, Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_export_default_or_another_module_format_instead); } - else if (modulekind === ModuleKind.System) { + else if (moduleKind === ModuleKind.System) { // system modules does not support export assignment grammarErrorOnNode(node, Diagnostics.Export_assignment_is_not_supported_when_module_flag_is_system); } @@ -27676,10 +27702,18 @@ namespace ts { } function checkGrammarMetaProperty(node: MetaProperty) { - if (node.keywordToken === SyntaxKind.NewKeyword) { - if (node.name.escapedText !== "target") { - return grammarErrorOnNode(node.name, Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.escapedText, tokenToString(node.keywordToken), "target"); - } + const escapedText = node.name.escapedText; + switch (node.keywordToken) { + case SyntaxKind.NewKeyword: + if (escapedText !== "target") { + return grammarErrorOnNode(node.name, Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.escapedText, tokenToString(node.keywordToken), "target"); + } + break; + case SyntaxKind.ImportKeyword: + if (escapedText !== "meta") { + return grammarErrorOnNode(node.name, Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.escapedText, tokenToString(node.keywordToken), "meta"); + } + break; } } @@ -27878,7 +27912,7 @@ namespace ts { } function checkGrammarImportCallExpression(node: ImportCall): boolean { - if (modulekind === ModuleKind.ES2015) { + if (moduleKind === ModuleKind.ES2015) { return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_be_used_when_targeting_ECMAScript_2015_modules); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index e81cd4fbc221a..46695ab2d75bf 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -971,6 +971,10 @@ "category": "Error", "code": 1342 }, + "The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options.": { + "category": "Error", + "code": 1343 + }, "Duplicate identifier '{0}'.": { "category": "Error", diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 8547eb171147a..32e7ca19dd313 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -540,7 +540,7 @@ namespace ts { const newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); // Because new source file node is created, it may not have the flag PossiblyContainDynamicImport. This is the case if there is no new edit to add dynamic import. // We will manually port the flag to the new source file. - newSourceFile.flags |= (sourceFile.flags & NodeFlags.PossiblyContainsDynamicImport); + newSourceFile.flags |= (sourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags); return newSourceFile; } @@ -2625,6 +2625,20 @@ namespace ts { return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken; } + function nextTokenIsDot() { + return nextToken() === SyntaxKind.DotToken; + } + + function nextTokenIsOpenParenOrLessThanOrDot() { + switch (nextToken()) { + case SyntaxKind.OpenParenToken: + case SyntaxKind.LessThanToken: + case SyntaxKind.DotToken: + return true; + } + return false; + } + function parseTypeLiteral(): TypeLiteralNode { const node = createNode(SyntaxKind.TypeLiteral); node.members = parseObjectTypeMembers(); @@ -3093,7 +3107,7 @@ namespace ts { case SyntaxKind.Identifier: return true; case SyntaxKind.ImportKeyword: - return lookAhead(nextTokenIsOpenParenOrLessThan); + return lookAhead(nextTokenIsOpenParenOrLessThanOrDot); default: return isIdentifier(); } @@ -3955,14 +3969,31 @@ namespace ts { // 3)we have a MemberExpression which either completes the LeftHandSideExpression, // or starts the beginning of the first four CallExpression productions. let expression: MemberExpression; - if (token() === SyntaxKind.ImportKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) { - // We don't want to eagerly consume all import keyword as import call expression so we look a head to find "(" - // For example: - // var foo3 = require("subfolder - // import * as foo1 from "module-from-node - // We want this import to be a statement rather than import call expression - sourceFile.flags |= NodeFlags.PossiblyContainsDynamicImport; - expression = parseTokenNode(); + if (token() === SyntaxKind.ImportKeyword) { + if (lookAhead(nextTokenIsOpenParenOrLessThan)) { + // We don't want to eagerly consume all import keyword as import call expression so we look ahead to find "(" + // For example: + // var foo3 = require("subfolder + // import * as foo1 from "module-from-node + // We want this import to be a statement rather than import call expression + sourceFile.flags |= NodeFlags.PossiblyContainsDynamicImport; + expression = parseTokenNode(); + } + else if (lookAhead(nextTokenIsDot)) { + // This is an 'import.*' metaproperty (i.e. 'import.meta') + const fullStart = scanner.getStartPos(); + nextToken(); // advance past the 'import' + nextToken(); // advance past the dot + const node = createNode(SyntaxKind.MetaProperty, fullStart) as MetaProperty; + node.keywordToken = SyntaxKind.ImportKeyword; + node.name = parseIdentifierName(); + expression = finishNode(node); + + sourceFile.flags |= NodeFlags.PossiblyContainsImportMeta; + } + else { + expression = parseMemberExpressionOrHigher(); + } } else { expression = token() === SyntaxKind.SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher(); @@ -4523,7 +4554,7 @@ namespace ts { case SyntaxKind.FunctionKeyword: return parseFunctionExpression(); case SyntaxKind.NewKeyword: - return parseNewExpression(); + return parseNewExpressionOrNewDotTarget(); case SyntaxKind.SlashToken: case SyntaxKind.SlashEqualsToken: if (reScanSlashToken() === SyntaxKind.RegularExpressionLiteral) { @@ -4674,7 +4705,7 @@ namespace ts { return isIdentifier() ? parseIdentifier() : undefined; } - function parseNewExpression(): NewExpression | MetaProperty { + function parseNewExpressionOrNewDotTarget(): NewExpression | MetaProperty { const fullStart = scanner.getStartPos(); parseExpected(SyntaxKind.NewKeyword); if (parseOptional(SyntaxKind.DotToken)) { @@ -5122,7 +5153,7 @@ namespace ts { return true; case SyntaxKind.ImportKeyword: - return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThan); + return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThanOrDot); case SyntaxKind.ConstKeyword: case SyntaxKind.ExportKeyword: @@ -6108,14 +6139,35 @@ namespace ts { } function setExternalModuleIndicator(sourceFile: SourceFile) { - sourceFile.externalModuleIndicator = forEach(sourceFile.statements, node => - hasModifier(node, ModifierFlags.Export) - || node.kind === SyntaxKind.ImportEqualsDeclaration && (node).moduleReference.kind === SyntaxKind.ExternalModuleReference - || node.kind === SyntaxKind.ImportDeclaration - || node.kind === SyntaxKind.ExportAssignment - || node.kind === SyntaxKind.ExportDeclaration + // Try to use the first top-level import/export when available, then + // fall back to looking for an 'import.meta' somewhere in the tree if necessary. + sourceFile.externalModuleIndicator = + forEach(sourceFile.statements, isAnExternalModuleIndicatorNode) || + getImportMetaIfNecessary(sourceFile); + } + + function isAnExternalModuleIndicatorNode(node: Node) { + return hasModifier(node, ModifierFlags.Export) + || node.kind === SyntaxKind.ImportEqualsDeclaration && (node).moduleReference.kind === SyntaxKind.ExternalModuleReference + || node.kind === SyntaxKind.ImportDeclaration + || node.kind === SyntaxKind.ExportAssignment + || node.kind === SyntaxKind.ExportDeclaration ? node - : undefined); + : undefined; + } + + function getImportMetaIfNecessary(sourceFile: SourceFile) { + return sourceFile.flags & NodeFlags.PossiblyContainsImportMeta ? + walkTreeForExternalModuleIndicators(sourceFile) : + undefined; + } + + function walkTreeForExternalModuleIndicators(node: Node): Node { + return isImportMeta(node) ? node : forEachChild(node, walkTreeForExternalModuleIndicators); + } + + function isImportMeta(node: Node): boolean { + return isMetaProperty(node) && node.keywordToken === SyntaxKind.ImportKeyword && node.name.escapedText === "meta"; } const enum ParsingContext { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 75cdd07845f2c..54dede025b597 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -986,7 +986,7 @@ namespace ts { // moduleAugmentations has changed oldProgram.structureIsReused = StructureIsReused.SafeModules; } - if ((oldSourceFile.flags & NodeFlags.PossiblyContainsDynamicImport) !== (newSourceFile.flags & NodeFlags.PossiblyContainsDynamicImport)) { + if ((oldSourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags) !== (newSourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags)) { // dynamicImport has changed oldProgram.structureIsReused = StructureIsReused.SafeModules; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 2aea2e2974202..2622fe3f5e44a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -490,19 +490,21 @@ namespace ts { ThisNodeOrAnySubNodesHasError = 1 << 17, // If this node or any of its children had an error HasAggregatedChildData = 1 << 18, // If we've computed data from children and cached it in this node - // This flag will be set when the parser encounters a dynamic import expression so that module resolution - // will not have to walk the tree if the flag is not set. However, this flag is just a approximation because - // once it is set, the flag never gets cleared (hence why it's named "PossiblyContainsDynamicImport"). - // During editing, if dynamic import is removed, incremental parsing will *NOT* update this flag. This means that the tree will always be traversed - // during module resolution. However, the removal operation should not occur often and in the case of the + // These flags will be set when the parser encounters a dynamic import expression or 'import.meta' to avoid + // walking the tree if the flags are not set. However, these flags are just a approximation + // (hence why it's named "PossiblyContainsDynamicImport") because once set, the flags never get cleared. + // During editing, if a dynamic import is removed, incremental parsing will *NOT* clear this flag. + // This means that the tree will always be traversed during module resolution, or when looking for external module indicators. + // However, the removal operation should not occur often and in the case of the // removal, it is likely that users will add the import anyway. // The advantage of this approach is its simplicity. For the case of batch compilation, // we guarantee that users won't have to pay the price of walking the tree if a dynamic import isn't used. - /* @internal */ - PossiblyContainsDynamicImport = 1 << 19, - JSDoc = 1 << 20, // If node was parsed inside jsdoc - /* @internal */ Ambient = 1 << 21, // If node was inside an ambient context -- a declaration file, or inside something with the `declare` modifier. - /* @internal */ InWithStatement = 1 << 22, // If any ancestor of node was the `statement` of a WithStatement (not the `expression`) + /* @internal */ PossiblyContainsDynamicImport = 1 << 19, + /* @internal */ PossiblyContainsImportMeta = 1 << 20, + + JSDoc = 1 << 21, // If node was parsed inside jsdoc + /* @internal */ Ambient = 1 << 22, // If node was inside an ambient context -- a declaration file, or inside something with the `declare` modifier. + /* @internal */ InWithStatement = 1 << 23, // If any ancestor of node was the `statement` of a WithStatement (not the `expression`) BlockScoped = Let | Const, @@ -514,6 +516,11 @@ namespace ts { // Exclude these flags when parsing a Type TypeExcludesFlags = YieldContext | AwaitContext, + + // Represents all flags that are potentially set once and + // never cleared on SourceFiles which get re-used in between incremental parses. + // See the comment above on `PossiblyContainsDynamicImport` and `PossiblyContainsImportMeta`. + /* @internal */ PermanentlySetIncrementalFlags = PossiblyContainsDynamicImport | PossiblyContainsImportMeta, } export const enum ModifierFlags { @@ -1756,7 +1763,7 @@ namespace ts { // for the same reasons we treat NewExpression as a PrimaryExpression. export interface MetaProperty extends PrimaryExpression { kind: SyntaxKind.MetaProperty; - keywordToken: SyntaxKind.NewKeyword; + keywordToken: SyntaxKind.NewKeyword | SyntaxKind.ImportKeyword; name: Identifier; } @@ -2557,7 +2564,11 @@ namespace ts { languageVersion: ScriptTarget; /* @internal */ scriptKind: ScriptKind; - // The first node that causes this file to be an external module + /** + * The first "most obvious" node that makes a file an external module. + * This is intended to be the first top-level import/export, + * but could be arbitrarily nested (e.g. `import.meta`). + */ /* @internal */ externalModuleIndicator: Node; // The first node that causes this file to be a CommonJS module /* @internal */ commonJsModuleIndicator: Node; diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 384d45cd75f07..0f1782ef3e6d4 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -507,6 +507,15 @@ interface TemplateStringsArray extends ReadonlyArray { readonly raw: ReadonlyArray; } +/** + * The type of `import.meta`. + * + * If you need to declare that a given property exists on `import.meta`, + * this type may be augmented via interface merging. + */ +interface ImportMeta { +} + interface Math { /** The mathematical constant e. This is Euler's number, the base of natural logarithms. */ readonly E: number; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 504d0c18d40ce..7a0a2b4676c0a 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -414,11 +414,11 @@ declare namespace ts { JavaScriptFile = 65536, ThisNodeOrAnySubNodesHasError = 131072, HasAggregatedChildData = 262144, - JSDoc = 1048576, + JSDoc = 2097152, BlockScoped = 3, ReachabilityCheckFlags = 384, ReachabilityAndEmitFlags = 1408, - ContextFlags = 6387712, + ContextFlags = 12679168, TypeExcludesFlags = 20480 } enum ModifierFlags { @@ -1072,7 +1072,7 @@ declare namespace ts { } interface MetaProperty extends PrimaryExpression { kind: SyntaxKind.MetaProperty; - keywordToken: SyntaxKind.NewKeyword; + keywordToken: SyntaxKind.NewKeyword | SyntaxKind.ImportKeyword; name: Identifier; } interface JsxElement extends PrimaryExpression { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 967fe44aab6c1..64b15eff9c08d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -414,11 +414,11 @@ declare namespace ts { JavaScriptFile = 65536, ThisNodeOrAnySubNodesHasError = 131072, HasAggregatedChildData = 262144, - JSDoc = 1048576, + JSDoc = 2097152, BlockScoped = 3, ReachabilityCheckFlags = 384, ReachabilityAndEmitFlags = 1408, - ContextFlags = 6387712, + ContextFlags = 12679168, TypeExcludesFlags = 20480 } enum ModifierFlags { @@ -1072,7 +1072,7 @@ declare namespace ts { } interface MetaProperty extends PrimaryExpression { kind: SyntaxKind.MetaProperty; - keywordToken: SyntaxKind.NewKeyword; + keywordToken: SyntaxKind.NewKeyword | SyntaxKind.ImportKeyword; name: Identifier; } interface JsxElement extends PrimaryExpression { diff --git a/tests/baselines/reference/importMeta.errors.txt b/tests/baselines/reference/importMeta.errors.txt new file mode 100644 index 0000000000000..999c883f26618 --- /dev/null +++ b/tests/baselines/reference/importMeta.errors.txt @@ -0,0 +1,71 @@ +error TS2468: Cannot find global value 'Promise'. +tests/cases/conformance/es2019/importMeta/assignmentTargets.ts(1,44): error TS2339: Property 'blah' does not exist on type 'ImportMeta'. +tests/cases/conformance/es2019/importMeta/assignmentTargets.ts(1,63): error TS2339: Property 'blue' does not exist on type 'ImportMeta'. +tests/cases/conformance/es2019/importMeta/assignmentTargets.ts(2,1): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. +tests/cases/conformance/es2019/importMeta/example.ts(2,2): error TS2705: An async function or method in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your `--lib` option. +tests/cases/conformance/es2019/importMeta/example.ts(3,71): error TS2339: Property 'url' does not exist on type 'ImportMeta'. +tests/cases/conformance/es2019/importMeta/example.ts(6,28): error TS2339: Property 'scriptElement' does not exist on type 'ImportMeta'. +tests/cases/conformance/es2019/importMeta/moduleLookingFile01.ts(2,23): error TS17012: 'metal' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? +tests/cases/conformance/es2019/importMeta/moduleLookingFile01.ts(3,23): error TS17012: 'import' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? +tests/cases/conformance/es2019/importMeta/scriptLookingFile01.ts(2,22): error TS17012: 'metal' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? +tests/cases/conformance/es2019/importMeta/scriptLookingFile01.ts(3,22): error TS17012: 'import' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? + + +!!! error TS2468: Cannot find global value 'Promise'. +==== tests/cases/conformance/es2019/importMeta/example.ts (3 errors) ==== + // Adapted from https://github.com/tc39/proposal-import-meta/tree/c3902a9ffe2e69a7ac42c19d7ea74cbdcea9b7fb#example + (async () => { + ~~~~~~~~~~~~~ +!!! error TS2705: An async function or method in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your `--lib` option. + const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); + ~~~ +!!! error TS2339: Property 'url' does not exist on type 'ImportMeta'. + const blob = await response.blob(); + + const size = import.meta.scriptElement.dataset.size || 300; + ~~~~~~~~~~~~~ +!!! error TS2339: Property 'scriptElement' does not exist on type 'ImportMeta'. + + const image = new Image(); + image.src = URL.createObjectURL(blob); + image.width = image.height = size; + + document.body.appendChild(image); + })(); + +==== tests/cases/conformance/es2019/importMeta/moduleLookingFile01.ts (2 errors) ==== + export let x = import.meta; + export let y = import.metal; + ~~~~~ +!!! error TS17012: 'metal' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? + export let z = import.import.import.malkovich; + ~~~~~~ +!!! error TS17012: 'import' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? + +==== tests/cases/conformance/es2019/importMeta/scriptLookingFile01.ts (2 errors) ==== + let globalA = import.meta; + let globalB = import.metal; + ~~~~~ +!!! error TS17012: 'metal' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? + let globalC = import.import.import.malkovich; + ~~~~~~ +!!! error TS17012: 'import' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? + +==== tests/cases/conformance/es2019/importMeta/assignmentTargets.ts (3 errors) ==== + export const foo: ImportMeta = import.meta.blah = import.meta.blue = import.meta; + ~~~~ +!!! error TS2339: Property 'blah' does not exist on type 'ImportMeta'. + ~~~~ +!!! error TS2339: Property 'blue' does not exist on type 'ImportMeta'. + import.meta = foo; + ~~~~~~~~~~~ +!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. + + // @Filename augmentations.ts + declare global { + interface ImportMeta { + wellKnownProperty: { a: number, b: string, c: boolean }; + } + } + + const { a, b, c } = import.meta.wellKnownProperty; \ No newline at end of file diff --git a/tests/baselines/reference/importMeta.js b/tests/baselines/reference/importMeta.js new file mode 100644 index 0000000000000..4b6fa5436f567 --- /dev/null +++ b/tests/baselines/reference/importMeta.js @@ -0,0 +1,63 @@ +//// [tests/cases/conformance/es2019/importMeta/importMeta.ts] //// + +//// [example.ts] +// Adapted from https://github.com/tc39/proposal-import-meta/tree/c3902a9ffe2e69a7ac42c19d7ea74cbdcea9b7fb#example +(async () => { + const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); + const blob = await response.blob(); + + const size = import.meta.scriptElement.dataset.size || 300; + + const image = new Image(); + image.src = URL.createObjectURL(blob); + image.width = image.height = size; + + document.body.appendChild(image); +})(); + +//// [moduleLookingFile01.ts] +export let x = import.meta; +export let y = import.metal; +export let z = import.import.import.malkovich; + +//// [scriptLookingFile01.ts] +let globalA = import.meta; +let globalB = import.metal; +let globalC = import.import.import.malkovich; + +//// [assignmentTargets.ts] +export const foo: ImportMeta = import.meta.blah = import.meta.blue = import.meta; +import.meta = foo; + +// @Filename augmentations.ts +declare global { + interface ImportMeta { + wellKnownProperty: { a: number, b: string, c: boolean }; + } +} + +const { a, b, c } = import.meta.wellKnownProperty; + +//// [example.js] +// Adapted from https://github.com/tc39/proposal-import-meta/tree/c3902a9ffe2e69a7ac42c19d7ea74cbdcea9b7fb#example +(async () => { + const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); + const blob = await response.blob(); + const size = import.meta.scriptElement.dataset.size || 300; + const image = new Image(); + image.src = URL.createObjectURL(blob); + image.width = image.height = size; + document.body.appendChild(image); +})(); +//// [moduleLookingFile01.js] +export let x = import.meta; +export let y = import.metal; +export let z = import.import.import.malkovich; +//// [scriptLookingFile01.js] +let globalA = import.meta; +let globalB = import.metal; +let globalC = import.import.import.malkovich; +//// [assignmentTargets.js] +export const foo = import.meta.blah = import.meta.blue = import.meta; +import.meta = foo; +const { a, b, c } = import.meta.wellKnownProperty; diff --git a/tests/baselines/reference/importMeta.symbols b/tests/baselines/reference/importMeta.symbols new file mode 100644 index 0000000000000..58d8f9807d4c1 --- /dev/null +++ b/tests/baselines/reference/importMeta.symbols @@ -0,0 +1,101 @@ +=== tests/cases/conformance/es2019/importMeta/example.ts === +// Adapted from https://github.com/tc39/proposal-import-meta/tree/c3902a9ffe2e69a7ac42c19d7ea74cbdcea9b7fb#example +(async () => { + const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); +>response : Symbol(response, Decl(example.ts, 2, 7)) +>fetch : Symbol(fetch, Decl(lib.dom.d.ts, --, --)) +>new URL("../hamsters.jpg", import.meta.url).toString : Symbol(URL.toString, Decl(lib.dom.d.ts, --, --)) +>URL : Symbol(URL, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) +>toString : Symbol(URL.toString, Decl(lib.dom.d.ts, --, --)) + + const blob = await response.blob(); +>blob : Symbol(blob, Decl(example.ts, 3, 7)) +>response.blob : Symbol(Body.blob, Decl(lib.dom.d.ts, --, --)) +>response : Symbol(response, Decl(example.ts, 2, 7)) +>blob : Symbol(Body.blob, Decl(lib.dom.d.ts, --, --)) + + const size = import.meta.scriptElement.dataset.size || 300; +>size : Symbol(size, Decl(example.ts, 5, 7)) + + const image = new Image(); +>image : Symbol(image, Decl(example.ts, 7, 7)) +>Image : Symbol(Image, Decl(lib.dom.d.ts, --, --)) + + image.src = URL.createObjectURL(blob); +>image.src : Symbol(HTMLImageElement.src, Decl(lib.dom.d.ts, --, --)) +>image : Symbol(image, Decl(example.ts, 7, 7)) +>src : Symbol(HTMLImageElement.src, Decl(lib.dom.d.ts, --, --)) +>URL.createObjectURL : Symbol(createObjectURL, Decl(lib.dom.d.ts, --, --)) +>URL : Symbol(URL, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) +>createObjectURL : Symbol(createObjectURL, Decl(lib.dom.d.ts, --, --)) +>blob : Symbol(blob, Decl(example.ts, 3, 7)) + + image.width = image.height = size; +>image.width : Symbol(HTMLImageElement.width, Decl(lib.dom.d.ts, --, --)) +>image : Symbol(image, Decl(example.ts, 7, 7)) +>width : Symbol(HTMLImageElement.width, Decl(lib.dom.d.ts, --, --)) +>image.height : Symbol(HTMLImageElement.height, Decl(lib.dom.d.ts, --, --)) +>image : Symbol(image, Decl(example.ts, 7, 7)) +>height : Symbol(HTMLImageElement.height, Decl(lib.dom.d.ts, --, --)) +>size : Symbol(size, Decl(example.ts, 5, 7)) + + document.body.appendChild(image); +>document.body.appendChild : Symbol(Node.appendChild, Decl(lib.dom.d.ts, --, --)) +>document.body : Symbol(Document.body, Decl(lib.dom.d.ts, --, --)) +>document : Symbol(document, Decl(lib.dom.d.ts, --, --)) +>body : Symbol(Document.body, Decl(lib.dom.d.ts, --, --)) +>appendChild : Symbol(Node.appendChild, Decl(lib.dom.d.ts, --, --)) +>image : Symbol(image, Decl(example.ts, 7, 7)) + +})(); + +=== tests/cases/conformance/es2019/importMeta/moduleLookingFile01.ts === +export let x = import.meta; +>x : Symbol(x, Decl(moduleLookingFile01.ts, 0, 10)) + +export let y = import.metal; +>y : Symbol(y, Decl(moduleLookingFile01.ts, 1, 10)) + +export let z = import.import.import.malkovich; +>z : Symbol(z, Decl(moduleLookingFile01.ts, 2, 10)) + +=== tests/cases/conformance/es2019/importMeta/scriptLookingFile01.ts === +let globalA = import.meta; +>globalA : Symbol(globalA, Decl(scriptLookingFile01.ts, 0, 3)) + +let globalB = import.metal; +>globalB : Symbol(globalB, Decl(scriptLookingFile01.ts, 1, 3)) + +let globalC = import.import.import.malkovich; +>globalC : Symbol(globalC, Decl(scriptLookingFile01.ts, 2, 3)) + +=== tests/cases/conformance/es2019/importMeta/assignmentTargets.ts === +export const foo: ImportMeta = import.meta.blah = import.meta.blue = import.meta; +>foo : Symbol(foo, Decl(assignmentTargets.ts, 0, 12)) +>ImportMeta : Symbol(ImportMeta, Decl(lib.es5.d.ts, --, --), Decl(assignmentTargets.ts, 4, 16)) + +import.meta = foo; +>foo : Symbol(foo, Decl(assignmentTargets.ts, 0, 12)) + +// @Filename augmentations.ts +declare global { +>global : Symbol(global, Decl(assignmentTargets.ts, 1, 18)) + + interface ImportMeta { +>ImportMeta : Symbol(ImportMeta, Decl(lib.es5.d.ts, --, --), Decl(assignmentTargets.ts, 4, 16)) + + wellKnownProperty: { a: number, b: string, c: boolean }; +>wellKnownProperty : Symbol(ImportMeta.wellKnownProperty, Decl(assignmentTargets.ts, 5, 24)) +>a : Symbol(a, Decl(assignmentTargets.ts, 6, 24)) +>b : Symbol(b, Decl(assignmentTargets.ts, 6, 35)) +>c : Symbol(c, Decl(assignmentTargets.ts, 6, 46)) + } +} + +const { a, b, c } = import.meta.wellKnownProperty; +>a : Symbol(a, Decl(assignmentTargets.ts, 10, 7)) +>b : Symbol(b, Decl(assignmentTargets.ts, 10, 10)) +>c : Symbol(c, Decl(assignmentTargets.ts, 10, 13)) +>import.meta.wellKnownProperty : Symbol(ImportMeta.wellKnownProperty, Decl(assignmentTargets.ts, 5, 24)) +>wellKnownProperty : Symbol(ImportMeta.wellKnownProperty, Decl(assignmentTargets.ts, 5, 24)) + diff --git a/tests/baselines/reference/importMeta.types b/tests/baselines/reference/importMeta.types new file mode 100644 index 0000000000000..c6140c8d05d03 --- /dev/null +++ b/tests/baselines/reference/importMeta.types @@ -0,0 +1,169 @@ +=== tests/cases/conformance/es2019/importMeta/example.ts === +// Adapted from https://github.com/tc39/proposal-import-meta/tree/c3902a9ffe2e69a7ac42c19d7ea74cbdcea9b7fb#example +(async () => { +>(async () => { const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); const blob = await response.blob(); const size = import.meta.scriptElement.dataset.size || 300; const image = new Image(); image.src = URL.createObjectURL(blob); image.width = image.height = size; document.body.appendChild(image);})() : Promise +>(async () => { const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); const blob = await response.blob(); const size = import.meta.scriptElement.dataset.size || 300; const image = new Image(); image.src = URL.createObjectURL(blob); image.width = image.height = size; document.body.appendChild(image);}) : () => Promise +>async () => { const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); const blob = await response.blob(); const size = import.meta.scriptElement.dataset.size || 300; const image = new Image(); image.src = URL.createObjectURL(blob); image.width = image.height = size; document.body.appendChild(image);} : () => Promise + + const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); +>response : Response +>await fetch(new URL("../hamsters.jpg", import.meta.url).toString()) : Response +>fetch(new URL("../hamsters.jpg", import.meta.url).toString()) : Promise +>fetch : (input?: string | Request, init?: RequestInit) => Promise +>new URL("../hamsters.jpg", import.meta.url).toString() : string +>new URL("../hamsters.jpg", import.meta.url).toString : () => string +>new URL("../hamsters.jpg", import.meta.url) : URL +>URL : { new (url: string, base?: string | URL): URL; prototype: URL; createObjectURL(object: any, options?: ObjectURLOptions): string; revokeObjectURL(url: string): void; } +>"../hamsters.jpg" : "../hamsters.jpg" +>import.meta.url : any +>import.meta : ImportMeta +>meta : any +>url : any +>toString : () => string + + const blob = await response.blob(); +>blob : Blob +>await response.blob() : Blob +>response.blob() : Promise +>response.blob : () => Promise +>response : Response +>blob : () => Promise + + const size = import.meta.scriptElement.dataset.size || 300; +>size : any +>import.meta.scriptElement.dataset.size || 300 : any +>import.meta.scriptElement.dataset.size : any +>import.meta.scriptElement.dataset : any +>import.meta.scriptElement : any +>import.meta : ImportMeta +>meta : any +>scriptElement : any +>dataset : any +>size : any +>300 : 300 + + const image = new Image(); +>image : HTMLImageElement +>new Image() : HTMLImageElement +>Image : new (width?: number, height?: number) => HTMLImageElement + + image.src = URL.createObjectURL(blob); +>image.src = URL.createObjectURL(blob) : string +>image.src : string +>image : HTMLImageElement +>src : string +>URL.createObjectURL(blob) : string +>URL.createObjectURL : (object: any, options?: ObjectURLOptions) => string +>URL : { new (url: string, base?: string | URL): URL; prototype: URL; createObjectURL(object: any, options?: ObjectURLOptions): string; revokeObjectURL(url: string): void; } +>createObjectURL : (object: any, options?: ObjectURLOptions) => string +>blob : Blob + + image.width = image.height = size; +>image.width = image.height = size : any +>image.width : number +>image : HTMLImageElement +>width : number +>image.height = size : any +>image.height : number +>image : HTMLImageElement +>height : number +>size : any + + document.body.appendChild(image); +>document.body.appendChild(image) : HTMLImageElement +>document.body.appendChild : (newChild: T) => T +>document.body : HTMLElement +>document : Document +>body : HTMLElement +>appendChild : (newChild: T) => T +>image : HTMLImageElement + +})(); + +=== tests/cases/conformance/es2019/importMeta/moduleLookingFile01.ts === +export let x = import.meta; +>x : ImportMeta +>import.meta : ImportMeta +>meta : any + +export let y = import.metal; +>y : any +>import.metal : any +>metal : any + +export let z = import.import.import.malkovich; +>z : any +>import.import.import.malkovich : any +>import.import.import : any +>import.import : any +>import : any +>import : any +>malkovich : any + +=== tests/cases/conformance/es2019/importMeta/scriptLookingFile01.ts === +let globalA = import.meta; +>globalA : ImportMeta +>import.meta : ImportMeta +>meta : any + +let globalB = import.metal; +>globalB : any +>import.metal : any +>metal : any + +let globalC = import.import.import.malkovich; +>globalC : any +>import.import.import.malkovich : any +>import.import.import : any +>import.import : any +>import : any +>import : any +>malkovich : any + +=== tests/cases/conformance/es2019/importMeta/assignmentTargets.ts === +export const foo: ImportMeta = import.meta.blah = import.meta.blue = import.meta; +>foo : ImportMeta +>ImportMeta : ImportMeta +>import.meta.blah = import.meta.blue = import.meta : ImportMeta +>import.meta.blah : any +>import.meta : ImportMeta +>meta : any +>blah : any +>import.meta.blue = import.meta : ImportMeta +>import.meta.blue : any +>import.meta : ImportMeta +>meta : any +>blue : any +>import.meta : ImportMeta +>meta : any + +import.meta = foo; +>import.meta = foo : ImportMeta +>import.meta : ImportMeta +>meta : any +>foo : ImportMeta + +// @Filename augmentations.ts +declare global { +>global : any + + interface ImportMeta { +>ImportMeta : ImportMeta + + wellKnownProperty: { a: number, b: string, c: boolean }; +>wellKnownProperty : { a: number; b: string; c: boolean; } +>a : number +>b : string +>c : boolean + } +} + +const { a, b, c } = import.meta.wellKnownProperty; +>a : number +>b : string +>c : boolean +>import.meta.wellKnownProperty : { a: number; b: string; c: boolean; } +>import.meta : ImportMeta +>meta : any +>wellKnownProperty : { a: number; b: string; c: boolean; } + diff --git a/tests/baselines/reference/importMetaES5.errors.txt b/tests/baselines/reference/importMetaES5.errors.txt new file mode 100644 index 0000000000000..71b67efae0143 --- /dev/null +++ b/tests/baselines/reference/importMetaES5.errors.txt @@ -0,0 +1,110 @@ +error TS2468: Cannot find global value 'Promise'. +tests/cases/conformance/es2019/importMeta/assignmentTargets.ts(1,32): error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. +tests/cases/conformance/es2019/importMeta/assignmentTargets.ts(1,44): error TS2339: Property 'blah' does not exist on type 'ImportMeta'. +tests/cases/conformance/es2019/importMeta/assignmentTargets.ts(1,51): error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. +tests/cases/conformance/es2019/importMeta/assignmentTargets.ts(1,63): error TS2339: Property 'blue' does not exist on type 'ImportMeta'. +tests/cases/conformance/es2019/importMeta/assignmentTargets.ts(1,70): error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. +tests/cases/conformance/es2019/importMeta/assignmentTargets.ts(2,1): error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. +tests/cases/conformance/es2019/importMeta/assignmentTargets.ts(2,1): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. +tests/cases/conformance/es2019/importMeta/assignmentTargets.ts(11,21): error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. +tests/cases/conformance/es2019/importMeta/example.ts(2,2): error TS2705: An async function or method in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your `--lib` option. +tests/cases/conformance/es2019/importMeta/example.ts(3,59): error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. +tests/cases/conformance/es2019/importMeta/example.ts(3,71): error TS2339: Property 'url' does not exist on type 'ImportMeta'. +tests/cases/conformance/es2019/importMeta/example.ts(6,16): error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. +tests/cases/conformance/es2019/importMeta/example.ts(6,28): error TS2339: Property 'scriptElement' does not exist on type 'ImportMeta'. +tests/cases/conformance/es2019/importMeta/moduleLookingFile01.ts(1,16): error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. +tests/cases/conformance/es2019/importMeta/moduleLookingFile01.ts(2,16): error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. +tests/cases/conformance/es2019/importMeta/moduleLookingFile01.ts(2,23): error TS17012: 'metal' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? +tests/cases/conformance/es2019/importMeta/moduleLookingFile01.ts(3,16): error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. +tests/cases/conformance/es2019/importMeta/moduleLookingFile01.ts(3,23): error TS17012: 'import' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? +tests/cases/conformance/es2019/importMeta/scriptLookingFile01.ts(1,15): error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. +tests/cases/conformance/es2019/importMeta/scriptLookingFile01.ts(2,15): error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. +tests/cases/conformance/es2019/importMeta/scriptLookingFile01.ts(2,22): error TS17012: 'metal' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? +tests/cases/conformance/es2019/importMeta/scriptLookingFile01.ts(3,15): error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. +tests/cases/conformance/es2019/importMeta/scriptLookingFile01.ts(3,22): error TS17012: 'import' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? + + +!!! error TS2468: Cannot find global value 'Promise'. +==== tests/cases/conformance/es2019/importMeta/example.ts (5 errors) ==== + // Adapted from https://github.com/tc39/proposal-import-meta/tree/c3902a9ffe2e69a7ac42c19d7ea74cbdcea9b7fb#example + (async () => { + ~~~~~~~~~~~~~ +!!! error TS2705: An async function or method in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your `--lib` option. + const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); + ~~~~~~~~~~~ +!!! error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. + ~~~ +!!! error TS2339: Property 'url' does not exist on type 'ImportMeta'. + const blob = await response.blob(); + + const size = import.meta.scriptElement.dataset.size || 300; + ~~~~~~~~~~~ +!!! error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. + ~~~~~~~~~~~~~ +!!! error TS2339: Property 'scriptElement' does not exist on type 'ImportMeta'. + + const image = new Image(); + image.src = URL.createObjectURL(blob); + image.width = image.height = size; + + document.body.appendChild(image); + })(); + +==== tests/cases/conformance/es2019/importMeta/moduleLookingFile01.ts (5 errors) ==== + export let x = import.meta; + ~~~~~~~~~~~ +!!! error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. + export let y = import.metal; + ~~~~~~~~~~~~ +!!! error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. + ~~~~~ +!!! error TS17012: 'metal' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? + export let z = import.import.import.malkovich; + ~~~~~~~~~~~~~ +!!! error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. + ~~~~~~ +!!! error TS17012: 'import' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? + +==== tests/cases/conformance/es2019/importMeta/scriptLookingFile01.ts (5 errors) ==== + let globalA = import.meta; + ~~~~~~~~~~~ +!!! error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. + let globalB = import.metal; + ~~~~~~~~~~~~ +!!! error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. + ~~~~~ +!!! error TS17012: 'metal' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? + let globalC = import.import.import.malkovich; + ~~~~~~~~~~~~~ +!!! error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. + ~~~~~~ +!!! error TS17012: 'import' is not a valid meta-property for keyword 'import'. Did you mean 'meta'? + +==== tests/cases/conformance/es2019/importMeta/assignmentTargets.ts (8 errors) ==== + export const foo: ImportMeta = import.meta.blah = import.meta.blue = import.meta; + ~~~~~~~~~~~ +!!! error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. + ~~~~ +!!! error TS2339: Property 'blah' does not exist on type 'ImportMeta'. + ~~~~~~~~~~~ +!!! error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. + ~~~~ +!!! error TS2339: Property 'blue' does not exist on type 'ImportMeta'. + ~~~~~~~~~~~ +!!! error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. + import.meta = foo; + ~~~~~~~~~~~ +!!! error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. + ~~~~~~~~~~~ +!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. + + // @Filename augmentations.ts + declare global { + interface ImportMeta { + wellKnownProperty: { a: number, b: string, c: boolean }; + } + } + + const { a, b, c } = import.meta.wellKnownProperty; + ~~~~~~~~~~~ +!!! error TS1343: The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options. \ No newline at end of file diff --git a/tests/baselines/reference/importMetaES5.js b/tests/baselines/reference/importMetaES5.js new file mode 100644 index 0000000000000..8ac695412ff7e --- /dev/null +++ b/tests/baselines/reference/importMetaES5.js @@ -0,0 +1,117 @@ +//// [tests/cases/conformance/es2019/importMeta/importMetaES5.ts] //// + +//// [example.ts] +// Adapted from https://github.com/tc39/proposal-import-meta/tree/c3902a9ffe2e69a7ac42c19d7ea74cbdcea9b7fb#example +(async () => { + const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); + const blob = await response.blob(); + + const size = import.meta.scriptElement.dataset.size || 300; + + const image = new Image(); + image.src = URL.createObjectURL(blob); + image.width = image.height = size; + + document.body.appendChild(image); +})(); + +//// [moduleLookingFile01.ts] +export let x = import.meta; +export let y = import.metal; +export let z = import.import.import.malkovich; + +//// [scriptLookingFile01.ts] +let globalA = import.meta; +let globalB = import.metal; +let globalC = import.import.import.malkovich; + +//// [assignmentTargets.ts] +export const foo: ImportMeta = import.meta.blah = import.meta.blue = import.meta; +import.meta = foo; + +// @Filename augmentations.ts +declare global { + interface ImportMeta { + wellKnownProperty: { a: number, b: string, c: boolean }; + } +} + +const { a, b, c } = import.meta.wellKnownProperty; + +//// [example.js] +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var _this = this; +Object.defineProperty(exports, "__esModule", { value: true }); +// Adapted from https://github.com/tc39/proposal-import-meta/tree/c3902a9ffe2e69a7ac42c19d7ea74cbdcea9b7fb#example +(function () { return __awaiter(_this, void 0, void 0, function () { + var response, blob, size, image; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, fetch(new URL("../hamsters.jpg", import.meta.url).toString())]; + case 1: + response = _a.sent(); + return [4 /*yield*/, response.blob()]; + case 2: + blob = _a.sent(); + size = import.meta.scriptElement.dataset.size || 300; + image = new Image(); + image.src = URL.createObjectURL(blob); + image.width = image.height = size; + document.body.appendChild(image); + return [2 /*return*/]; + } + }); +}); })(); +//// [moduleLookingFile01.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.x = (import.meta); +exports.y = (import.metal); +exports.z = import.import.import.malkovich; +//// [scriptLookingFile01.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var globalA = import.meta; +var globalB = import.metal; +var globalC = import.import.import.malkovich; +//// [assignmentTargets.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.foo = import.meta.blah = import.meta.blue = import.meta; +import.meta = exports.foo; +var _a = import.meta.wellKnownProperty, a = _a.a, b = _a.b, c = _a.c; diff --git a/tests/baselines/reference/importMetaES5.symbols b/tests/baselines/reference/importMetaES5.symbols new file mode 100644 index 0000000000000..58d8f9807d4c1 --- /dev/null +++ b/tests/baselines/reference/importMetaES5.symbols @@ -0,0 +1,101 @@ +=== tests/cases/conformance/es2019/importMeta/example.ts === +// Adapted from https://github.com/tc39/proposal-import-meta/tree/c3902a9ffe2e69a7ac42c19d7ea74cbdcea9b7fb#example +(async () => { + const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); +>response : Symbol(response, Decl(example.ts, 2, 7)) +>fetch : Symbol(fetch, Decl(lib.dom.d.ts, --, --)) +>new URL("../hamsters.jpg", import.meta.url).toString : Symbol(URL.toString, Decl(lib.dom.d.ts, --, --)) +>URL : Symbol(URL, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) +>toString : Symbol(URL.toString, Decl(lib.dom.d.ts, --, --)) + + const blob = await response.blob(); +>blob : Symbol(blob, Decl(example.ts, 3, 7)) +>response.blob : Symbol(Body.blob, Decl(lib.dom.d.ts, --, --)) +>response : Symbol(response, Decl(example.ts, 2, 7)) +>blob : Symbol(Body.blob, Decl(lib.dom.d.ts, --, --)) + + const size = import.meta.scriptElement.dataset.size || 300; +>size : Symbol(size, Decl(example.ts, 5, 7)) + + const image = new Image(); +>image : Symbol(image, Decl(example.ts, 7, 7)) +>Image : Symbol(Image, Decl(lib.dom.d.ts, --, --)) + + image.src = URL.createObjectURL(blob); +>image.src : Symbol(HTMLImageElement.src, Decl(lib.dom.d.ts, --, --)) +>image : Symbol(image, Decl(example.ts, 7, 7)) +>src : Symbol(HTMLImageElement.src, Decl(lib.dom.d.ts, --, --)) +>URL.createObjectURL : Symbol(createObjectURL, Decl(lib.dom.d.ts, --, --)) +>URL : Symbol(URL, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) +>createObjectURL : Symbol(createObjectURL, Decl(lib.dom.d.ts, --, --)) +>blob : Symbol(blob, Decl(example.ts, 3, 7)) + + image.width = image.height = size; +>image.width : Symbol(HTMLImageElement.width, Decl(lib.dom.d.ts, --, --)) +>image : Symbol(image, Decl(example.ts, 7, 7)) +>width : Symbol(HTMLImageElement.width, Decl(lib.dom.d.ts, --, --)) +>image.height : Symbol(HTMLImageElement.height, Decl(lib.dom.d.ts, --, --)) +>image : Symbol(image, Decl(example.ts, 7, 7)) +>height : Symbol(HTMLImageElement.height, Decl(lib.dom.d.ts, --, --)) +>size : Symbol(size, Decl(example.ts, 5, 7)) + + document.body.appendChild(image); +>document.body.appendChild : Symbol(Node.appendChild, Decl(lib.dom.d.ts, --, --)) +>document.body : Symbol(Document.body, Decl(lib.dom.d.ts, --, --)) +>document : Symbol(document, Decl(lib.dom.d.ts, --, --)) +>body : Symbol(Document.body, Decl(lib.dom.d.ts, --, --)) +>appendChild : Symbol(Node.appendChild, Decl(lib.dom.d.ts, --, --)) +>image : Symbol(image, Decl(example.ts, 7, 7)) + +})(); + +=== tests/cases/conformance/es2019/importMeta/moduleLookingFile01.ts === +export let x = import.meta; +>x : Symbol(x, Decl(moduleLookingFile01.ts, 0, 10)) + +export let y = import.metal; +>y : Symbol(y, Decl(moduleLookingFile01.ts, 1, 10)) + +export let z = import.import.import.malkovich; +>z : Symbol(z, Decl(moduleLookingFile01.ts, 2, 10)) + +=== tests/cases/conformance/es2019/importMeta/scriptLookingFile01.ts === +let globalA = import.meta; +>globalA : Symbol(globalA, Decl(scriptLookingFile01.ts, 0, 3)) + +let globalB = import.metal; +>globalB : Symbol(globalB, Decl(scriptLookingFile01.ts, 1, 3)) + +let globalC = import.import.import.malkovich; +>globalC : Symbol(globalC, Decl(scriptLookingFile01.ts, 2, 3)) + +=== tests/cases/conformance/es2019/importMeta/assignmentTargets.ts === +export const foo: ImportMeta = import.meta.blah = import.meta.blue = import.meta; +>foo : Symbol(foo, Decl(assignmentTargets.ts, 0, 12)) +>ImportMeta : Symbol(ImportMeta, Decl(lib.es5.d.ts, --, --), Decl(assignmentTargets.ts, 4, 16)) + +import.meta = foo; +>foo : Symbol(foo, Decl(assignmentTargets.ts, 0, 12)) + +// @Filename augmentations.ts +declare global { +>global : Symbol(global, Decl(assignmentTargets.ts, 1, 18)) + + interface ImportMeta { +>ImportMeta : Symbol(ImportMeta, Decl(lib.es5.d.ts, --, --), Decl(assignmentTargets.ts, 4, 16)) + + wellKnownProperty: { a: number, b: string, c: boolean }; +>wellKnownProperty : Symbol(ImportMeta.wellKnownProperty, Decl(assignmentTargets.ts, 5, 24)) +>a : Symbol(a, Decl(assignmentTargets.ts, 6, 24)) +>b : Symbol(b, Decl(assignmentTargets.ts, 6, 35)) +>c : Symbol(c, Decl(assignmentTargets.ts, 6, 46)) + } +} + +const { a, b, c } = import.meta.wellKnownProperty; +>a : Symbol(a, Decl(assignmentTargets.ts, 10, 7)) +>b : Symbol(b, Decl(assignmentTargets.ts, 10, 10)) +>c : Symbol(c, Decl(assignmentTargets.ts, 10, 13)) +>import.meta.wellKnownProperty : Symbol(ImportMeta.wellKnownProperty, Decl(assignmentTargets.ts, 5, 24)) +>wellKnownProperty : Symbol(ImportMeta.wellKnownProperty, Decl(assignmentTargets.ts, 5, 24)) + diff --git a/tests/baselines/reference/importMetaES5.types b/tests/baselines/reference/importMetaES5.types new file mode 100644 index 0000000000000..c6140c8d05d03 --- /dev/null +++ b/tests/baselines/reference/importMetaES5.types @@ -0,0 +1,169 @@ +=== tests/cases/conformance/es2019/importMeta/example.ts === +// Adapted from https://github.com/tc39/proposal-import-meta/tree/c3902a9ffe2e69a7ac42c19d7ea74cbdcea9b7fb#example +(async () => { +>(async () => { const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); const blob = await response.blob(); const size = import.meta.scriptElement.dataset.size || 300; const image = new Image(); image.src = URL.createObjectURL(blob); image.width = image.height = size; document.body.appendChild(image);})() : Promise +>(async () => { const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); const blob = await response.blob(); const size = import.meta.scriptElement.dataset.size || 300; const image = new Image(); image.src = URL.createObjectURL(blob); image.width = image.height = size; document.body.appendChild(image);}) : () => Promise +>async () => { const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); const blob = await response.blob(); const size = import.meta.scriptElement.dataset.size || 300; const image = new Image(); image.src = URL.createObjectURL(blob); image.width = image.height = size; document.body.appendChild(image);} : () => Promise + + const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); +>response : Response +>await fetch(new URL("../hamsters.jpg", import.meta.url).toString()) : Response +>fetch(new URL("../hamsters.jpg", import.meta.url).toString()) : Promise +>fetch : (input?: string | Request, init?: RequestInit) => Promise +>new URL("../hamsters.jpg", import.meta.url).toString() : string +>new URL("../hamsters.jpg", import.meta.url).toString : () => string +>new URL("../hamsters.jpg", import.meta.url) : URL +>URL : { new (url: string, base?: string | URL): URL; prototype: URL; createObjectURL(object: any, options?: ObjectURLOptions): string; revokeObjectURL(url: string): void; } +>"../hamsters.jpg" : "../hamsters.jpg" +>import.meta.url : any +>import.meta : ImportMeta +>meta : any +>url : any +>toString : () => string + + const blob = await response.blob(); +>blob : Blob +>await response.blob() : Blob +>response.blob() : Promise +>response.blob : () => Promise +>response : Response +>blob : () => Promise + + const size = import.meta.scriptElement.dataset.size || 300; +>size : any +>import.meta.scriptElement.dataset.size || 300 : any +>import.meta.scriptElement.dataset.size : any +>import.meta.scriptElement.dataset : any +>import.meta.scriptElement : any +>import.meta : ImportMeta +>meta : any +>scriptElement : any +>dataset : any +>size : any +>300 : 300 + + const image = new Image(); +>image : HTMLImageElement +>new Image() : HTMLImageElement +>Image : new (width?: number, height?: number) => HTMLImageElement + + image.src = URL.createObjectURL(blob); +>image.src = URL.createObjectURL(blob) : string +>image.src : string +>image : HTMLImageElement +>src : string +>URL.createObjectURL(blob) : string +>URL.createObjectURL : (object: any, options?: ObjectURLOptions) => string +>URL : { new (url: string, base?: string | URL): URL; prototype: URL; createObjectURL(object: any, options?: ObjectURLOptions): string; revokeObjectURL(url: string): void; } +>createObjectURL : (object: any, options?: ObjectURLOptions) => string +>blob : Blob + + image.width = image.height = size; +>image.width = image.height = size : any +>image.width : number +>image : HTMLImageElement +>width : number +>image.height = size : any +>image.height : number +>image : HTMLImageElement +>height : number +>size : any + + document.body.appendChild(image); +>document.body.appendChild(image) : HTMLImageElement +>document.body.appendChild : (newChild: T) => T +>document.body : HTMLElement +>document : Document +>body : HTMLElement +>appendChild : (newChild: T) => T +>image : HTMLImageElement + +})(); + +=== tests/cases/conformance/es2019/importMeta/moduleLookingFile01.ts === +export let x = import.meta; +>x : ImportMeta +>import.meta : ImportMeta +>meta : any + +export let y = import.metal; +>y : any +>import.metal : any +>metal : any + +export let z = import.import.import.malkovich; +>z : any +>import.import.import.malkovich : any +>import.import.import : any +>import.import : any +>import : any +>import : any +>malkovich : any + +=== tests/cases/conformance/es2019/importMeta/scriptLookingFile01.ts === +let globalA = import.meta; +>globalA : ImportMeta +>import.meta : ImportMeta +>meta : any + +let globalB = import.metal; +>globalB : any +>import.metal : any +>metal : any + +let globalC = import.import.import.malkovich; +>globalC : any +>import.import.import.malkovich : any +>import.import.import : any +>import.import : any +>import : any +>import : any +>malkovich : any + +=== tests/cases/conformance/es2019/importMeta/assignmentTargets.ts === +export const foo: ImportMeta = import.meta.blah = import.meta.blue = import.meta; +>foo : ImportMeta +>ImportMeta : ImportMeta +>import.meta.blah = import.meta.blue = import.meta : ImportMeta +>import.meta.blah : any +>import.meta : ImportMeta +>meta : any +>blah : any +>import.meta.blue = import.meta : ImportMeta +>import.meta.blue : any +>import.meta : ImportMeta +>meta : any +>blue : any +>import.meta : ImportMeta +>meta : any + +import.meta = foo; +>import.meta = foo : ImportMeta +>import.meta : ImportMeta +>meta : any +>foo : ImportMeta + +// @Filename augmentations.ts +declare global { +>global : any + + interface ImportMeta { +>ImportMeta : ImportMeta + + wellKnownProperty: { a: number, b: string, c: boolean }; +>wellKnownProperty : { a: number; b: string; c: boolean; } +>a : number +>b : string +>c : boolean + } +} + +const { a, b, c } = import.meta.wellKnownProperty; +>a : number +>b : string +>c : boolean +>import.meta.wellKnownProperty : { a: number; b: string; c: boolean; } +>import.meta : ImportMeta +>meta : any +>wellKnownProperty : { a: number; b: string; c: boolean; } + diff --git a/tests/cases/conformance/es2019/importMeta/importMeta.ts b/tests/cases/conformance/es2019/importMeta/importMeta.ts new file mode 100644 index 0000000000000..71d635a6534cc --- /dev/null +++ b/tests/cases/conformance/es2019/importMeta/importMeta.ts @@ -0,0 +1,42 @@ + +// @target: esnext +// @module: esnext +// @lib: es5,dom + +// @Filename: example.ts +// Adapted from https://github.com/tc39/proposal-import-meta/tree/c3902a9ffe2e69a7ac42c19d7ea74cbdcea9b7fb#example +(async () => { + const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); + const blob = await response.blob(); + + const size = import.meta.scriptElement.dataset.size || 300; + + const image = new Image(); + image.src = URL.createObjectURL(blob); + image.width = image.height = size; + + document.body.appendChild(image); +})(); + +// @Filename: moduleLookingFile01.ts +export let x = import.meta; +export let y = import.metal; +export let z = import.import.import.malkovich; + +// @Filename: scriptLookingFile01.ts +let globalA = import.meta; +let globalB = import.metal; +let globalC = import.import.import.malkovich; + +// @Filename: assignmentTargets.ts +export const foo: ImportMeta = import.meta.blah = import.meta.blue = import.meta; +import.meta = foo; + +// @Filename augmentations.ts +declare global { + interface ImportMeta { + wellKnownProperty: { a: number, b: string, c: boolean }; + } +} + +const { a, b, c } = import.meta.wellKnownProperty; \ No newline at end of file diff --git a/tests/cases/conformance/es2019/importMeta/importMetaES5.ts b/tests/cases/conformance/es2019/importMeta/importMetaES5.ts new file mode 100644 index 0000000000000..b11a32ecc9b22 --- /dev/null +++ b/tests/cases/conformance/es2019/importMeta/importMetaES5.ts @@ -0,0 +1,42 @@ + +// @target: es5 +// @module: commonjs +// @lib: es5,dom + +// @Filename: example.ts +// Adapted from https://github.com/tc39/proposal-import-meta/tree/c3902a9ffe2e69a7ac42c19d7ea74cbdcea9b7fb#example +(async () => { + const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString()); + const blob = await response.blob(); + + const size = import.meta.scriptElement.dataset.size || 300; + + const image = new Image(); + image.src = URL.createObjectURL(blob); + image.width = image.height = size; + + document.body.appendChild(image); +})(); + +// @Filename: moduleLookingFile01.ts +export let x = import.meta; +export let y = import.metal; +export let z = import.import.import.malkovich; + +// @Filename: scriptLookingFile01.ts +let globalA = import.meta; +let globalB = import.metal; +let globalC = import.import.import.malkovich; + +// @Filename: assignmentTargets.ts +export const foo: ImportMeta = import.meta.blah = import.meta.blue = import.meta; +import.meta = foo; + +// @Filename augmentations.ts +declare global { + interface ImportMeta { + wellKnownProperty: { a: number, b: string, c: boolean }; + } +} + +const { a, b, c } = import.meta.wellKnownProperty; \ No newline at end of file