diff --git a/.yarnrc b/.yarnrc new file mode 100644 index 00000000000..acaaffdb73e --- /dev/null +++ b/.yarnrc @@ -0,0 +1 @@ +--install.no-lockfile true diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 4540a4409d6..660b19a5872 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -3229,8 +3229,7 @@ namespace ts { // A ClassDeclaration is ES6 syntax. transformFlags = subtreeFlags | TransformFlags.AssertES2015; - // A class with a parameter property assignment, property initializer, computed property name, or decorator is - // TypeScript syntax. + // A class with a parameter property assignment or decorator is TypeScript syntax. // An exported declaration may be TypeScript syntax, but is handled by the visitor // for a namespace declaration. if ((subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax) @@ -3247,8 +3246,7 @@ namespace ts { // A ClassExpression is ES6 syntax. let transformFlags = subtreeFlags | TransformFlags.AssertES2015; - // A class with a parameter property assignment, property initializer, or decorator is - // TypeScript syntax. + // A class with a parameter property assignment or decorator is TypeScript syntax. if (subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax || node.typeParameters) { transformFlags |= TransformFlags.AssertTypeScript; @@ -3338,7 +3336,6 @@ namespace ts { || hasModifier(node, ModifierFlags.TypeScriptModifier) || node.typeParameters || node.type - || (node.name && isComputedPropertyName(node.name)) // While computed method names aren't typescript, the TS transform must visit them to emit property declarations correctly || !node.body) { transformFlags |= TransformFlags.AssertTypeScript; } @@ -3369,7 +3366,6 @@ namespace ts { if (node.decorators || hasModifier(node, ModifierFlags.TypeScriptModifier) || node.type - || (node.name && isComputedPropertyName(node.name)) // While computed accessor names aren't typescript, the TS transform must visit them to emit property declarations correctly || !node.body) { transformFlags |= TransformFlags.AssertTypeScript; } @@ -3384,12 +3380,15 @@ namespace ts { } function computePropertyDeclaration(node: PropertyDeclaration, subtreeFlags: TransformFlags) { - // A PropertyDeclaration is TypeScript syntax. - let transformFlags = subtreeFlags | TransformFlags.AssertTypeScript; + let transformFlags = subtreeFlags | TransformFlags.ContainsClassFields; - // If the PropertyDeclaration has an initializer or a computed name, we need to inform its ancestor - // so that it handle the transformation. - if (node.initializer || isComputedPropertyName(node.name)) { + // Decorators, TypeScript-specific modifiers, and type annotations are TypeScript syntax. + if (some(node.decorators) || hasModifier(node, ModifierFlags.TypeScriptModifier) || node.type) { + transformFlags |= TransformFlags.AssertTypeScript; + } + + // Hoisted variables related to class properties should live within the TypeScript class wrapper. + if (isComputedPropertyName(node.name) || (hasStaticModifier(node) && node.initializer)) { transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index b209a878804..529484956e6 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4990,7 +4990,10 @@ "category": "Message", "code": 95079 }, - + "Infer 'this' type of '{0}' from usage": { + "category": "Message", + "code": 95080 + }, "No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": { "category": "Error", "code": 18004 diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index ec14260c6f5..ac276bafd83 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2204,6 +2204,13 @@ namespace ts { return tag; } + /** @internal */ + export function createJSDocThisTag(typeExpression?: JSDocTypeExpression): JSDocThisTag { + const tag = createJSDocTag(SyntaxKind.JSDocThisTag, "this"); + tag.typeExpression = typeExpression; + return tag; + } + /* @internal */ export function createJSDocParamTag(name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, comment?: string): JSDocParameterTag { const tag = createJSDocTag(SyntaxKind.JSDocParameterTag, "param"); @@ -3119,6 +3126,18 @@ namespace ts { return node.emitNode; } + /** + * Sets `EmitFlags.NoComments` on a node and removes any leading and trailing synthetic comments. + * @internal + */ + export function removeAllComments(node: T): T { + const emitNode = getOrCreateEmitNode(node); + emitNode.flags |= EmitFlags.NoComments; + emitNode.leadingComments = undefined; + emitNode.trailingComments = undefined; + return node; + } + export function setTextRange(range: T, location: TextRange | undefined): T { if (location) { range.pos = location.pos; diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index 1c1df9bb0c2..d520571e6df 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -44,6 +44,7 @@ namespace ts { addRange(transformers, customTransformers && map(customTransformers.before, wrapScriptTransformerFactory)); transformers.push(transformTypeScript); + transformers.push(transformClassFields); if (jsx === JsxEmit.React) { transformers.push(transformJsx); diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts new file mode 100644 index 00000000000..048e4623656 --- /dev/null +++ b/src/compiler/transformers/classFields.ts @@ -0,0 +1,511 @@ +/*@internal*/ +namespace ts { + const enum ClassPropertySubstitutionFlags { + /** + * Enables substitutions for class expressions with static fields + * which have initializers that reference the class name. + */ + ClassAliases = 1 << 0, + } + /** + * Transforms ECMAScript Class Syntax. + * TypeScript parameter property syntax is transformed in the TypeScript transformer. + * For now, this transforms public field declarations using TypeScript class semantics + * (where the declarations get elided and initializers are transformed as assignments in the constructor). + * Eventually, this transform will change to the ECMAScript semantics (with Object.defineProperty). + */ + export function transformClassFields(context: TransformationContext) { + const { + hoistVariableDeclaration, + endLexicalEnvironment, + resumeLexicalEnvironment + } = context; + const resolver = context.getEmitResolver(); + + const previousOnSubstituteNode = context.onSubstituteNode; + context.onSubstituteNode = onSubstituteNode; + + let enabledSubstitutions: ClassPropertySubstitutionFlags; + + let classAliases: Identifier[]; + + /** + * Tracks what computed name expressions originating from elided names must be inlined + * at the next execution site, in document order + */ + let pendingExpressions: Expression[] | undefined; + + /** + * Tracks what computed name expression statements and static property initializers must be + * emitted at the next execution site, in document order (for decorated classes). + */ + let pendingStatements: Statement[] | undefined; + + return chainBundle(transformSourceFile); + + function transformSourceFile(node: SourceFile) { + if (node.isDeclarationFile) { + return node; + } + const visited = visitEachChild(node, visitor, context); + addEmitHelpers(visited, context.readEmitHelpers()); + return visited; + } + + function visitor(node: Node): VisitResult { + if (!(node.transformFlags & TransformFlags.ContainsClassFields)) return node; + + switch (node.kind) { + case SyntaxKind.ClassExpression: + return visitClassExpression(node as ClassExpression); + case SyntaxKind.ClassDeclaration: + return visitClassDeclaration(node as ClassDeclaration); + case SyntaxKind.VariableStatement: + return visitVariableStatement(node as VariableStatement); + } + return visitEachChild(node, visitor, context); + } + + /** + * Visits the members of a class that has fields. + * + * @param node The node to visit. + */ + function classElementVisitor(node: Node): VisitResult { + switch (node.kind) { + case SyntaxKind.Constructor: + // Constructors for classes using class fields are transformed in + // `visitClassDeclaration` or `visitClassExpression`. + return undefined; + + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodDeclaration: + // Visit the name of the member (if it's a computed property name). + return visitEachChild(node, classElementVisitor, context); + + case SyntaxKind.PropertyDeclaration: + return visitPropertyDeclaration(node as PropertyDeclaration); + + case SyntaxKind.ComputedPropertyName: + return visitComputedPropertyName(node as ComputedPropertyName); + + case SyntaxKind.SemicolonClassElement: + return node; + + default: + return visitor(node); + } + } + + function visitVariableStatement(node: VariableStatement) { + const savedPendingStatements = pendingStatements; + pendingStatements = []; + + const visitedNode = visitEachChild(node, visitor, context); + const statement = some(pendingStatements) ? + [visitedNode, ...pendingStatements] : + visitedNode; + + pendingStatements = savedPendingStatements; + return statement; + } + + function visitComputedPropertyName(name: ComputedPropertyName) { + let node = visitEachChild(name, visitor, context); + if (some(pendingExpressions)) { + const expressions = pendingExpressions; + expressions.push(name.expression); + pendingExpressions = []; + node = updateComputedPropertyName( + node, + inlineExpressions(expressions) + ); + } + return node; + } + + function visitPropertyDeclaration(node: PropertyDeclaration) { + Debug.assert(!some(node.decorators)); + // Create a temporary variable to store a computed property name (if necessary). + // If it's not inlineable, then we emit an expression after the class which assigns + // the property name to the temporary variable. + const expr = getPropertyNameExpressionIfNeeded(node.name, !!node.initializer); + if (expr && !isSimpleInlineableExpression(expr)) { + (pendingExpressions || (pendingExpressions = [])).push(expr); + } + return undefined; + } + + function visitClassDeclaration(node: ClassDeclaration) { + if (!forEach(node.members, isPropertyDeclaration)) { + return visitEachChild(node, visitor, context); + } + + const savedPendingExpressions = pendingExpressions; + pendingExpressions = undefined!; + + const extendsClauseElement = getEffectiveBaseTypeNode(node); + const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); + + const statements: Statement[] = [ + updateClassDeclaration( + node, + /*decorators*/ undefined, + node.modifiers, + node.name, + /*typeParameters*/ undefined, + visitNodes(node.heritageClauses, visitor, isHeritageClause), + transformClassMembers(node, isDerivedClass) + ) + ]; + + // Write any pending expressions from elided or moved computed property names + if (some(pendingExpressions)) { + statements.push(createExpressionStatement(inlineExpressions(pendingExpressions))); + } + + pendingExpressions = savedPendingExpressions; + + // Emit static property assignment. Because classDeclaration is lexically evaluated, + // it is safe to emit static property assignment after classDeclaration + // From ES6 specification: + // HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using + // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration. + const staticProperties = getInitializedProperties(node, /*isStatic*/ true); + if (some(staticProperties)) { + addInitializedPropertyStatements(statements, staticProperties, getInternalName(node)); + } + + return statements; + } + + function visitClassExpression(node: ClassExpression): Expression { + if (!forEach(node.members, isPropertyDeclaration)) { + return visitEachChild(node, visitor, context); + } + const savedPendingExpressions = pendingExpressions; + pendingExpressions = undefined; + + // If this class expression is a transformation of a decorated class declaration, + // then we want to output the pendingExpressions as statements, not as inlined + // expressions with the class statement. + // + // In this case, we use pendingStatements to produce the same output as the + // class declaration transformation. The VariableStatement visitor will insert + // these statements after the class expression variable statement. + const isDecoratedClassDeclaration = isClassDeclaration(getOriginalNode(node)); + + const staticProperties = getInitializedProperties(node, /*isStatic*/ true); + const extendsClauseElement = getEffectiveBaseTypeNode(node); + const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); + + const classExpression = updateClassExpression( + node, + node.modifiers, + node.name, + /*typeParameters*/ undefined, + visitNodes(node.heritageClauses, visitor, isHeritageClause), + transformClassMembers(node, isDerivedClass) + ); + + if (some(staticProperties) || some(pendingExpressions)) { + if (isDecoratedClassDeclaration) { + Debug.assertDefined(pendingStatements, "Decorated classes transformed by TypeScript are expected to be within a variable declaration."); + + // Write any pending expressions from elided or moved computed property names + if (pendingStatements && pendingExpressions && some(pendingExpressions)) { + pendingStatements.push(createExpressionStatement(inlineExpressions(pendingExpressions))); + } + pendingExpressions = savedPendingExpressions; + + if (pendingStatements && some(staticProperties)) { + addInitializedPropertyStatements(pendingStatements, staticProperties, getInternalName(node)); + } + return classExpression; + } + else { + const expressions: Expression[] = []; + const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference; + const temp = createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference); + if (isClassWithConstructorReference) { + // record an alias as the class name is not in scope for statics. + enableSubstitutionForClassAliases(); + const alias = getSynthesizedClone(temp); + alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; + classAliases[getOriginalNodeId(node)] = alias; + } + + // To preserve the behavior of the old emitter, we explicitly indent + // the body of a class with static initializers. + setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression)); + expressions.push(startOnNewLine(createAssignment(temp, classExpression))); + // Add any pending expressions leftover from elided or relocated computed property names + addRange(expressions, map(pendingExpressions, startOnNewLine)); + addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp)); + expressions.push(startOnNewLine(temp)); + + pendingExpressions = savedPendingExpressions; + return inlineExpressions(expressions); + } + } + + pendingExpressions = savedPendingExpressions; + return classExpression; + } + + function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + const members: ClassElement[] = []; + const constructor = transformConstructor(node, isDerivedClass); + if (constructor) { + members.push(constructor); + } + addRange(members, visitNodes(node.members, classElementVisitor, isClassElement)); + return setTextRange(createNodeArray(members), /*location*/ node.members); + } + + function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + const constructor = visitNode(getFirstConstructorWithBody(node), visitor, isConstructorDeclaration); + const containsPropertyInitializer = forEach(node.members, isInitializedProperty); + if (!containsPropertyInitializer) { + return constructor; + } + const parameters = visitParameterList(constructor ? constructor.parameters : undefined, visitor, context); + const body = transformConstructorBody(node, constructor, isDerivedClass); + if (!body) { + return undefined; + } + return startOnNewLine( + setOriginalNode( + setTextRange( + createConstructor( + /*decorators*/ undefined, + /*modifiers*/ undefined, + parameters, + body + ), + constructor || node + ), + constructor + ) + ); + } + + function transformConstructorBody(node: ClassDeclaration | ClassExpression, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) { + const properties = getInitializedProperties(node, /*isStatic*/ false); + + // Only generate synthetic constructor when there are property initializers to move. + if (!constructor && !some(properties)) { + return visitFunctionBody(/*node*/ undefined, visitor, context); + } + + resumeLexicalEnvironment(); + + let indexOfFirstStatement = 0; + let statements: Statement[] = []; + + if (!constructor && isDerivedClass) { + // Add a synthetic `super` call: + // + // super(...arguments); + // + statements.push( + createExpressionStatement( + createCall( + createSuper(), + /*typeArguments*/ undefined, + [createSpread(createIdentifier("arguments"))] + ) + ) + ); + } + + if (constructor) { + indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements, visitor); + } + + // Add the property initializers. Transforms this: + // + // public x = 1; + // + // Into this: + // + // constructor() { + // this.x = 1; + // } + // + if (constructor && constructor.body) { + let parameterPropertyDeclarationCount = 0; + for (let i = indexOfFirstStatement; i < constructor.body.statements.length; i++) { + if (isParameterPropertyDeclaration(getOriginalNode(constructor.body.statements[i]))) { + parameterPropertyDeclarationCount++; + } + else { + break; + } + } + if (parameterPropertyDeclarationCount > 0) { + addRange(statements, visitNodes(constructor.body.statements, visitor, isStatement, indexOfFirstStatement, parameterPropertyDeclarationCount)); + indexOfFirstStatement += parameterPropertyDeclarationCount; + } + } + addInitializedPropertyStatements(statements, properties, createThis()); + + // Add existing statements, skipping the initial super call. + if (constructor) { + addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement)); + } + + statements = mergeLexicalEnvironment(statements, endLexicalEnvironment()); + + return setTextRange( + createBlock( + setTextRange( + createNodeArray(statements), + /*location*/ constructor ? constructor.body!.statements : node.members + ), + /*multiLine*/ true + ), + /*location*/ constructor ? constructor.body : undefined + ); + } + + /** + * Generates assignment statements for property initializers. + * + * @param properties An array of property declarations to transform. + * @param receiver The receiver on which each property should be assigned. + */ + function addInitializedPropertyStatements(statements: Statement[], properties: ReadonlyArray, receiver: LeftHandSideExpression) { + for (const property of properties) { + const statement = createExpressionStatement(transformInitializedProperty(property, receiver)); + setSourceMapRange(statement, moveRangePastModifiers(property)); + setCommentRange(statement, property); + setOriginalNode(statement, property); + statements.push(statement); + } + } + + /** + * Generates assignment expressions for property initializers. + * + * @param properties An array of property declarations to transform. + * @param receiver The receiver on which each property should be assigned. + */ + function generateInitializedPropertyExpressions(properties: ReadonlyArray, receiver: LeftHandSideExpression) { + const expressions: Expression[] = []; + for (const property of properties) { + const expression = transformInitializedProperty(property, receiver); + startOnNewLine(expression); + setSourceMapRange(expression, moveRangePastModifiers(property)); + setCommentRange(expression, property); + setOriginalNode(expression, property); + expressions.push(expression); + } + + return expressions; + } + + /** + * Transforms a property initializer into an assignment statement. + * + * @param property The property declaration. + * @param receiver The object receiving the property assignment. + */ + function transformInitializedProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) { + // We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name) + const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) + ? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name)) + : property.name; + const initializer = visitNode(property.initializer, visitor, isExpression); + const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); + + return createAssignment(memberAccess, initializer); + } + + function enableSubstitutionForClassAliases() { + if ((enabledSubstitutions & ClassPropertySubstitutionFlags.ClassAliases) === 0) { + enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases; + + // We need to enable substitutions for identifiers. This allows us to + // substitute class names inside of a class declaration. + context.enableSubstitution(SyntaxKind.Identifier); + + // Keep track of class aliases. + classAliases = []; + } + } + + /** + * Hooks node substitutions. + * + * @param hint The context for the emitter. + * @param node The node to substitute. + */ + function onSubstituteNode(hint: EmitHint, node: Node) { + node = previousOnSubstituteNode(hint, node); + if (hint === EmitHint.Expression) { + return substituteExpression(node as Expression); + } + return node; + } + + function substituteExpression(node: Expression) { + switch (node.kind) { + case SyntaxKind.Identifier: + return substituteExpressionIdentifier(node as Identifier); + } + return node; + } + + function substituteExpressionIdentifier(node: Identifier): Expression { + return trySubstituteClassAlias(node) || node; + } + + function trySubstituteClassAlias(node: Identifier): Expression | undefined { + if (enabledSubstitutions & ClassPropertySubstitutionFlags.ClassAliases) { + if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ConstructorReferenceInClass) { + // Due to the emit for class decorators, any reference to the class from inside of the class body + // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind + // behavior of class names in ES6. + // Also, when emitting statics for class expressions, we must substitute a class alias for + // constructor references in static property initializers. + const declaration = resolver.getReferencedValueDeclaration(node); + if (declaration) { + const classAlias = classAliases[declaration.id!]; // TODO: GH#18217 + if (classAlias) { + const clone = getSynthesizedClone(classAlias); + setSourceMapRange(clone, node); + setCommentRange(clone, node); + return clone; + } + } + } + } + + return undefined; + } + + + /** + * If the name is a computed property, this function transforms it, then either returns an expression which caches the + * value of the result or the expression itself if the value is either unused or safe to inline into multiple locations + * @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator) + */ + function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean): Expression | undefined { + if (isComputedPropertyName(name)) { + const expression = visitNode(name.expression, visitor, isExpression); + const innerExpression = skipPartiallyEmittedExpressions(expression); + const inlinable = isSimpleInlineableExpression(innerExpression); + const alreadyTransformed = isAssignmentExpression(innerExpression) && isGeneratedIdentifier(innerExpression.left); + if (!alreadyTransformed && !inlinable && shouldHoist) { + const generatedName = getGeneratedNameForNode(name); + hoistVariableDeclaration(generatedName); + return createAssignment(generatedName, expression); + } + return (inlinable || isIdentifier(innerExpression)) ? undefined : expression; + } + } + } + +} diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index db3d866e9f6..7623d19dd25 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -1567,7 +1567,7 @@ namespace ts { break; default: - Debug.failBadSyntaxKind(node); + Debug.failBadSyntaxKind(member, currentSourceFile && currentSourceFile.fileName); break; } } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index ee366eac249..af1679bef88 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -64,6 +64,7 @@ namespace ts { let currentLexicalScope: SourceFile | Block | ModuleBlock | CaseBlock; let currentNameScope: ClassDeclaration | undefined; let currentScopeFirstDeclarationsOfName: UnderscoreEscapedMap | undefined; + let currentClassHasParameterProperties: boolean | undefined; /** * Keeps track of whether expression substitution has been enabled for specific edge cases. @@ -83,12 +84,6 @@ namespace ts { */ let applicableSubstitutions: TypeScriptSubstitutionFlags; - /** - * Tracks what computed name expressions originating from elided names must be inlined - * at the next execution site, in document order - */ - let pendingExpressions: Expression[] | undefined; - return transformSourceFileOrBundle; function transformSourceFileOrBundle(node: SourceFile | Bundle) { @@ -136,6 +131,7 @@ namespace ts { const savedCurrentScope = currentLexicalScope; const savedCurrentNameScope = currentNameScope; const savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName; + const savedCurrentClassHasParameterProperties = currentClassHasParameterProperties; // Handle state changes before visiting a node. onBeforeVisitNode(node); @@ -149,6 +145,7 @@ namespace ts { currentLexicalScope = savedCurrentScope; currentNameScope = savedCurrentNameScope; + currentClassHasParameterProperties = savedCurrentClassHasParameterProperties; return visited; } @@ -315,12 +312,12 @@ namespace ts { function classElementVisitorWorker(node: Node): VisitResult { switch (node.kind) { case SyntaxKind.Constructor: - // TypeScript constructors are transformed in `visitClassDeclaration`. - // We elide them here as `visitorWorker` checks transform flags, which could - // erronously include an ES6 constructor without TypeScript syntax. - return undefined; + return visitConstructor(node as ConstructorDeclaration); case SyntaxKind.PropertyDeclaration: + // Property declarations are not TypeScript syntax, but they must be visited + // for the decorator transformation. + return visitPropertyDeclaration(node as PropertyDeclaration); case SyntaxKind.IndexSignature: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: @@ -437,7 +434,6 @@ namespace ts { // - decorators // - optional `implements` heritage clause // - parameter property assignments in the constructor - // - property declarations // - index signatures // - method overload signatures return visitClassDeclaration(node); @@ -449,7 +445,6 @@ namespace ts { // - decorators // - optional `implements` heritage clause // - parameter property assignments in the constructor - // - property declarations // - index signatures // - method overload signatures return visitClassExpression(node); @@ -612,9 +607,6 @@ namespace ts { return visitEachChild(node, visitor, context); } - const savedPendingExpressions = pendingExpressions; - pendingExpressions = undefined; - const staticProperties = getInitializedProperties(node, /*isStatic*/ true); const facts = getClassFacts(node, staticProperties); @@ -624,25 +616,11 @@ namespace ts { const name = node.name || (facts & ClassFacts.NeedsName ? getGeneratedNameForNode(node) : undefined); const classStatement = facts & ClassFacts.HasConstructorDecorators - ? createClassDeclarationHeadWithDecorators(node, name, facts) + ? createClassDeclarationHeadWithDecorators(node, name) : createClassDeclarationHeadWithoutDecorators(node, name, facts); let statements: Statement[] = [classStatement]; - // Write any pending expressions from elided or moved computed property names - if (some(pendingExpressions)) { - statements.push(createExpressionStatement(inlineExpressions(pendingExpressions!))); - } - pendingExpressions = savedPendingExpressions; - - // Emit static property assignment. Because classDeclaration is lexically evaluated, - // it is safe to emit static property assignment after classDeclaration - // From ES6 specification: - // HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using - // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration. - if (facts & ClassFacts.HasStaticInitializedProperties) { - addInitializedPropertyStatements(statements, staticProperties, facts & ClassFacts.UseImmediatelyInvokedFunctionExpression ? getInternalName(node) : getLocalName(node)); - } // Write any decorators of the node. addClassElementDecorationStatements(statements, node, /*isStatic*/ false); @@ -745,7 +723,7 @@ namespace ts { name, /*typeParameters*/ undefined, visitNodes(node.heritageClauses, visitor, isHeritageClause), - transformClassMembers(node, (facts & ClassFacts.IsDerivedClass) !== 0) + transformClassMembers(node) ); // To better align with the old emitter, we should not emit a trailing source map @@ -755,6 +733,7 @@ namespace ts { emitFlags |= EmitFlags.NoTrailingSourceMap; } + aggregateTransformFlags(classDeclaration); setTextRange(classDeclaration, node); setOriginalNode(classDeclaration, node); setEmitFlags(classDeclaration, emitFlags); @@ -765,7 +744,7 @@ namespace ts { * Transforms a decorated class declaration and appends the resulting statements. If * the class requires an alias to avoid issues with double-binding, the alias is returned. */ - function createClassDeclarationHeadWithDecorators(node: ClassDeclaration, name: Identifier | undefined, facts: ClassFacts) { + function createClassDeclarationHeadWithDecorators(node: ClassDeclaration, name: Identifier | undefined) { // When we emit an ES6 class that has a class decorator, we must tailor the // emit to certain specific cases. // @@ -860,8 +839,9 @@ namespace ts { // ${members} // } const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause); - const members = transformClassMembers(node, (facts & ClassFacts.IsDerivedClass) !== 0); + const members = transformClassMembers(node); const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members); + aggregateTransformFlags(classExpression); setOriginalNode(classExpression, node); setTextRange(classExpression, location); @@ -888,49 +868,18 @@ namespace ts { return visitEachChild(node, visitor, context); } - const savedPendingExpressions = pendingExpressions; - pendingExpressions = undefined; - - const staticProperties = getInitializedProperties(node, /*isStatic*/ true); - const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause); - const members = transformClassMembers(node, some(heritageClauses, c => c.token === SyntaxKind.ExtendsKeyword)); - const classExpression = createClassExpression( /*modifiers*/ undefined, node.name, /*typeParameters*/ undefined, - heritageClauses, - members + visitNodes(node.heritageClauses, visitor, isHeritageClause), + transformClassMembers(node) ); + aggregateTransformFlags(classExpression); setOriginalNode(classExpression, node); setTextRange(classExpression, node); - if (some(staticProperties) || some(pendingExpressions)) { - const expressions: Expression[] = []; - const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference; - const temp = createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference); - if (isClassWithConstructorReference) { - // record an alias as the class name is not in scope for statics. - enableSubstitutionForClassAliases(); - const alias = getSynthesizedClone(temp); - alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; - classAliases[getOriginalNodeId(node)] = alias; - } - - // To preserve the behavior of the old emitter, we explicitly indent - // the body of a class with static initializers. - setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression)); - expressions.push(startOnNewLine(createAssignment(temp, classExpression))); - // Add any pending expressions leftover from elided or relocated computed property names - addRange(expressions, map(pendingExpressions, startOnNewLine)); - pendingExpressions = savedPendingExpressions; - addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp)); - expressions.push(startOnNewLine(temp)); - return inlineExpressions(expressions); - } - - pendingExpressions = savedPendingExpressions; return classExpression; } @@ -938,344 +887,31 @@ namespace ts { * Transforms the members of a class. * * @param node The current class. - * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. */ - function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + function transformClassMembers(node: ClassDeclaration | ClassExpression) { const members: ClassElement[] = []; - const constructor = transformConstructor(node, isDerivedClass); - if (constructor) { - members.push(constructor); + const constructor = getFirstConstructorWithBody(node); + const parametersWithPropertyAssignments = constructor && + filter(constructor.parameters, isParameterPropertyDeclaration); + + if (parametersWithPropertyAssignments) { + for (const parameter of parametersWithPropertyAssignments) { + if (isIdentifier(parameter.name)) { + members.push(aggregateTransformFlags(createProperty( + /*decorators*/ undefined, + /*modifiers*/ undefined, + parameter.name, + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined))); + } + } } addRange(members, visitNodes(node.members, classElementVisitor, isClassElement)); return setTextRange(createNodeArray(members), /*location*/ node.members); } - /** - * Transforms (or creates) a constructor for a class. - * - * @param node The current class. - * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. - */ - function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { - // Check if we have property assignment inside class declaration. - // If there is a property assignment, we need to emit constructor whether users define it or not - // If there is no property assignment, we can omit constructor if users do not define it - const constructor = getFirstConstructorWithBody(node); - const hasInstancePropertyWithInitializer = forEach(node.members, isInstanceInitializedProperty); - const hasParameterPropertyAssignments = constructor && - constructor.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax && - forEach(constructor.parameters, isParameterWithPropertyAssignment); - - // If the class does not contain nodes that require a synthesized constructor, - // accept the current constructor if it exists. - if (!hasInstancePropertyWithInitializer && !hasParameterPropertyAssignments) { - return visitEachChild(constructor, visitor, context); - } - - const parameters = transformConstructorParameters(constructor); - const body = transformConstructorBody(node, constructor, isDerivedClass); - - // constructor(${parameters}) { - // ${body} - // } - return startOnNewLine( - setOriginalNode( - setTextRange( - createConstructor( - /*decorators*/ undefined, - /*modifiers*/ undefined, - parameters, - body - ), - constructor || node - ), - constructor - ) - ); - } - - /** - * Transforms (or creates) the parameters for the constructor of a class with - * parameter property assignments or instance property initializers. - * - * @param constructor The constructor declaration. - */ - function transformConstructorParameters(constructor: ConstructorDeclaration | undefined) { - // The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation: - // If constructor is empty, then - // If ClassHeritag_eopt is present and protoParent is not null, then - // Let constructor be the result of parsing the source text - // constructor(...args) { super (...args);} - // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. - // Else, - // Let constructor be the result of parsing the source text - // constructor( ){ } - // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. - // - // While we could emit the '...args' rest parameter, certain later tools in the pipeline might - // downlevel the '...args' portion less efficiently by naively copying the contents of 'arguments' to an array. - // Instead, we'll avoid using a rest parameter and spread into the super call as - // 'super(...arguments)' instead of 'super(...args)', as you can see in "transformConstructorBody". - return visitParameterList(constructor && constructor.parameters, visitor, context) - || []; - } - - /** - * Transforms (or creates) a constructor body for a class with parameter property - * assignments or instance property initializers. - * - * @param node The current class. - * @param constructor The current class constructor. - * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. - */ - function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) { - let statements: Statement[] = []; - let indexOfFirstStatement = 0; - - resumeLexicalEnvironment(); - - if (constructor) { - indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements); - - // Add parameters with property assignments. Transforms this: - // - // constructor (public x, public y) { - // } - // - // Into this: - // - // constructor (x, y) { - // this.x = x; - // this.y = y; - // } - // - const propertyAssignments = getParametersWithPropertyAssignments(constructor); - addRange(statements, map(propertyAssignments, transformParameterWithPropertyAssignment)); - } - else if (isDerivedClass) { - // Add a synthetic `super` call: - // - // super(...arguments); - // - statements.push( - createExpressionStatement( - createCall( - createSuper(), - /*typeArguments*/ undefined, - [createSpread(createIdentifier("arguments"))] - ) - ) - ); - } - - // Add the property initializers. Transforms this: - // - // public x = 1; - // - // Into this: - // - // constructor() { - // this.x = 1; - // } - // - const properties = getInitializedProperties(node, /*isStatic*/ false); - addInitializedPropertyStatements(statements, properties, createThis()); - - if (constructor) { - // The class already had a constructor, so we should add the existing statements, skipping the initial super call. - addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement)); - } - - // End the lexical environment. - statements = mergeLexicalEnvironment(statements, endLexicalEnvironment()); - return setTextRange( - createBlock( - setTextRange( - createNodeArray(statements), - /*location*/ constructor ? constructor.body!.statements : node.members - ), - /*multiLine*/ true - ), - /*location*/ constructor ? constructor.body : undefined - ); - } - - /** - * Adds super call and preceding prologue directives into the list of statements. - * - * @param ctor The constructor node. - * @returns index of the statement that follows super call - */ - function addPrologueDirectivesAndInitialSuperCall(ctor: ConstructorDeclaration, result: Statement[]): number { - if (ctor.body) { - const statements = ctor.body.statements; - // add prologue directives to the list (if any) - const index = addPrologue(result, statements, /*ensureUseStrict*/ false, visitor); - if (index === statements.length) { - // list contains nothing but prologue directives (or empty) - exit - return index; - } - - const statement = statements[index]; - if (statement.kind === SyntaxKind.ExpressionStatement && isSuperCall((statement).expression)) { - result.push(visitNode(statement, visitor, isStatement)); - return index + 1; - } - - return index; - } - - return 0; - } - - /** - * Gets all parameters of a constructor that should be transformed into property assignments. - * - * @param node The constructor node. - */ - function getParametersWithPropertyAssignments(node: ConstructorDeclaration): ReadonlyArray { - return filter(node.parameters, isParameterWithPropertyAssignment); - } - - /** - * Determines whether a parameter should be transformed into a property assignment. - * - * @param parameter The parameter node. - */ - function isParameterWithPropertyAssignment(parameter: ParameterDeclaration) { - return hasModifier(parameter, ModifierFlags.ParameterPropertyModifier) - && isIdentifier(parameter.name); - } - - /** - * Transforms a parameter into a property assignment statement. - * - * @param node The parameter declaration. - */ - function transformParameterWithPropertyAssignment(node: ParameterDeclaration) { - Debug.assert(isIdentifier(node.name)); - const name = node.name as Identifier; - const propertyName = getMutableClone(name); - setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoSourceMap); - - const localName = getMutableClone(name); - setEmitFlags(localName, EmitFlags.NoComments); - - return startOnNewLine( - setEmitFlags( - setTextRange( - createExpressionStatement( - createAssignment( - setTextRange( - createPropertyAccess( - createThis(), - propertyName - ), - node.name - ), - localName - ) - ), - moveRangePos(node, -1) - ), - EmitFlags.NoComments - ) - ); - } - - /** - * Gets all property declarations with initializers on either the static or instance side of a class. - * - * @param node The class node. - * @param isStatic A value indicating whether to get properties from the static or instance side of the class. - */ - function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): ReadonlyArray { - return filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty); - } - - /** - * Gets a value indicating whether a class element is a static property declaration with an initializer. - * - * @param member The class element node. - */ - function isStaticInitializedProperty(member: ClassElement): member is PropertyDeclaration { - return isInitializedProperty(member, /*isStatic*/ true); - } - - /** - * Gets a value indicating whether a class element is an instance property declaration with an initializer. - * - * @param member The class element node. - */ - function isInstanceInitializedProperty(member: ClassElement): member is PropertyDeclaration { - return isInitializedProperty(member, /*isStatic*/ false); - } - - /** - * Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer. - * - * @param member The class element node. - * @param isStatic A value indicating whether the member should be a static or instance member. - */ - function isInitializedProperty(member: ClassElement, isStatic: boolean) { - return member.kind === SyntaxKind.PropertyDeclaration - && isStatic === hasModifier(member, ModifierFlags.Static) - && (member).initializer !== undefined; - } - - /** - * Generates assignment statements for property initializers. - * - * @param properties An array of property declarations to transform. - * @param receiver The receiver on which each property should be assigned. - */ - function addInitializedPropertyStatements(statements: Statement[], properties: ReadonlyArray, receiver: LeftHandSideExpression) { - for (const property of properties) { - const statement = createExpressionStatement(transformInitializedProperty(property, receiver)); - setSourceMapRange(statement, moveRangePastModifiers(property)); - setCommentRange(statement, property); - setOriginalNode(statement, property); - statements.push(statement); - } - } - - /** - * Generates assignment expressions for property initializers. - * - * @param properties An array of property declarations to transform. - * @param receiver The receiver on which each property should be assigned. - */ - function generateInitializedPropertyExpressions(properties: ReadonlyArray, receiver: LeftHandSideExpression) { - const expressions: Expression[] = []; - for (const property of properties) { - const expression = transformInitializedProperty(property, receiver); - startOnNewLine(expression); - setSourceMapRange(expression, moveRangePastModifiers(property)); - setCommentRange(expression, property); - setOriginalNode(expression, property); - expressions.push(expression); - } - - return expressions; - } - - /** - * Transforms a property initializer into an assignment statement. - * - * @param property The property declaration. - * @param receiver The object receiving the property assignment. - */ - function transformInitializedProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) { - // We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name) - const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) - ? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name)) - : property.name; - const initializer = visitNode(property.initializer, visitor, isExpression); - const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); - - return createAssignment(memberAccess, initializer); - } /** * Gets either the static or instance members of a class that are decorated, or have @@ -2144,16 +1780,6 @@ namespace ts { : createIdentifier("BigInt"); } - /** - * A simple inlinable expression is an expression which can be copied into multiple locations - * without risk of repeating any sideeffects and whose value could not possibly change between - * any such locations - */ - function isSimpleInlineableExpression(expression: Expression) { - return !isIdentifier(expression) && isSimpleCopiableExpression(expression) || - isWellKnownSymbolSyntactically(expression); - } - /** * Gets an expression that represents a property name. For a computed property, a * name is generated for the node. @@ -2175,26 +1801,6 @@ namespace ts { } } - /** - * If the name is a computed property, this function transforms it, then either returns an expression which caches the - * value of the result or the expression itself if the value is either unused or safe to inline into multiple locations - * @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator) - * @param omitSimple Should expressions with no observable side-effects be elided? (ie, the expression is not hoisted for a decorator or initializer and is a literal) - */ - function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean, omitSimple: boolean): Expression | undefined { - if (isComputedPropertyName(name)) { - const expression = visitNode(name.expression, visitor, isExpression); - const innerExpression = skipPartiallyEmittedExpressions(expression); - const inlinable = isSimpleInlineableExpression(innerExpression); - if (!inlinable && shouldHoist) { - const generatedName = getGeneratedNameForNode(name); - hoistVariableDeclaration(generatedName); - return createAssignment(generatedName, expression); - } - return (omitSimple && (inlinable || isIdentifier(innerExpression))) ? undefined : expression; - } - } - /** * Visits the property name of a class element, for use when emitting property * initializers. For a computed property on a node with decorators, a temporary @@ -2204,18 +1810,20 @@ namespace ts { */ function visitPropertyNameOfClassElement(member: ClassElement): PropertyName { const name = member.name!; - let expr = getPropertyNameExpressionIfNeeded(name, some(member.decorators), /*omitSimple*/ false); - if (expr) { // expr only exists if `name` is a computed property name - // Inline any pending expressions from previous elided or relocated computed property name expressions in order to preserve execution order - if (some(pendingExpressions)) { - expr = inlineExpressions([...pendingExpressions, expr]); - pendingExpressions.length = 0; + // Computed property names need to be transformed into a hoisted variable when they are used more than once. + // The names are used more than once when: + // - the property is non-static and its initializer is moved to the constructor (when there are parameter property assignments). + // - the property has a decorator. + if (isComputedPropertyName(name) && ((!hasStaticModifier(member) && currentClassHasParameterProperties) || some(member.decorators))) { + const expression = visitNode(name.expression, visitor, isExpression); + const innerExpression = skipPartiallyEmittedExpressions(expression); + if (!isSimpleInlineableExpression(innerExpression)) { + const generatedName = getGeneratedNameForNode(name); + hoistVariableDeclaration(generatedName); + return updateComputedPropertyName(name, createAssignment(generatedName, expression)); } - return updateComputedPropertyName(name as ComputedPropertyName, expr); - } - else { - return name; } + return visitNode(name, visitor, isPropertyName); } /** @@ -2257,16 +1865,27 @@ namespace ts { * * @param node The declaration node. */ - function shouldEmitFunctionLikeDeclaration(node: FunctionLikeDeclaration) { + function shouldEmitFunctionLikeDeclaration(node: T): node is T & { body: NonNullable } { return !nodeIsMissing(node.body); } - function visitPropertyDeclaration(node: PropertyDeclaration): undefined { - const expr = getPropertyNameExpressionIfNeeded(node.name, some(node.decorators) || !!node.initializer, /*omitSimple*/ true); - if (expr && !isSimpleInlineableExpression(expr)) { - (pendingExpressions || (pendingExpressions = [])).push(expr); + function visitPropertyDeclaration(node: PropertyDeclaration) { + const updated = updateProperty( + node, + /*decorators*/ undefined, + visitNodes(node.modifiers, visitor, isModifier), + visitPropertyNameOfClassElement(node), + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + visitNode(node.initializer, visitor) + ); + if (updated !== node) { + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. + setCommentRange(updated, node); + setSourceMapRange(updated, moveRangePastDecorators(node)); } - return undefined; + return updated; } function visitConstructor(node: ConstructorDeclaration) { @@ -2276,10 +1895,90 @@ namespace ts { return updateConstructor( node, - visitNodes(node.decorators, visitor, isDecorator), - visitNodes(node.modifiers, visitor, isModifier), + /*decorators*/ undefined, + /*modifiers*/ undefined, visitParameterList(node.parameters, visitor, context), - visitFunctionBody(node.body, visitor, context) + transformConstructorBody(node.body, node) + ); + } + + function transformConstructorBody(body: Block, constructor: ConstructorDeclaration) { + const parametersWithPropertyAssignments = constructor && + filter(constructor.parameters, isParameterPropertyDeclaration); + if (!some(parametersWithPropertyAssignments)) { + return visitFunctionBody(body, visitor, context); + } + + let statements: Statement[] = []; + let indexOfFirstStatement = 0; + + resumeLexicalEnvironment(); + + indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements, visitor); + + // Add parameters with property assignments. Transforms this: + // + // constructor (public x, public y) { + // } + // + // Into this: + // + // constructor (x, y) { + // this.x = x; + // this.y = y; + // } + // + addRange(statements, map(parametersWithPropertyAssignments, transformParameterWithPropertyAssignment)); + + // Add the existing statements, skipping the initial super call. + addRange(statements, visitNodes(body.statements, visitor, isStatement, indexOfFirstStatement)); + + // End the lexical environment. + statements = mergeLexicalEnvironment(statements, endLexicalEnvironment()); + const block = createBlock(setTextRange(createNodeArray(statements), body.statements), /*multiLine*/ true); + setTextRange(block, /*location*/ body); + setOriginalNode(block, body); + return block; + } + + /** + * Transforms a parameter into a property assignment statement. + * + * @param node The parameter declaration. + */ + function transformParameterWithPropertyAssignment(node: ParameterPropertyDeclaration) { + const name = node.name; + if (!isIdentifier(name)) { + return undefined; + } + + const propertyName = getMutableClone(name); + setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoSourceMap); + + const localName = getMutableClone(name); + setEmitFlags(localName, EmitFlags.NoComments); + + return startOnNewLine( + removeAllComments( + setTextRange( + setOriginalNode( + createExpressionStatement( + createAssignment( + setTextRange( + createPropertyAccess( + createThis(), + propertyName + ), + node.name + ), + localName + ) + ), + node + ), + moveRangePos(node, -1) + ) + ) ); } @@ -2418,6 +2117,7 @@ namespace ts { if (parameterIsThisKeyword(node)) { return undefined; } + const updated = updateParameter( node, /*decorators*/ undefined, diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index 09239d7765f..f5f8a298a49 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -240,6 +240,47 @@ namespace ts { isIdentifier(expression); } + /** + * A simple inlinable expression is an expression which can be copied into multiple locations + * without risk of repeating any sideeffects and whose value could not possibly change between + * any such locations + */ + export function isSimpleInlineableExpression(expression: Expression) { + return !isIdentifier(expression) && isSimpleCopiableExpression(expression) || + isWellKnownSymbolSyntactically(expression); + } + + /** + * Adds super call and preceding prologue directives into the list of statements. + * + * @param ctor The constructor node. + * @param result The list of statements. + * @param visitor The visitor to apply to each node added to the result array. + * @returns index of the statement that follows super call + */ + export function addPrologueDirectivesAndInitialSuperCall(ctor: ConstructorDeclaration, result: Statement[], visitor: Visitor): number { + if (ctor.body) { + const statements = ctor.body.statements; + // add prologue directives to the list (if any) + const index = addPrologue(result, statements, /*ensureUseStrict*/ false, visitor); + if (index === statements.length) { + // list contains nothing but prologue directives (or empty) - exit + return index; + } + + const statement = statements[index]; + if (statement.kind === SyntaxKind.ExpressionStatement && isSuperCall((statement).expression)) { + result.push(visitNode(statement, visitor, isStatement)); + return index + 1; + } + + return index; + } + + return 0; + } + + /** * @param input Template string input strings * @param args Names which need to be made file-level unique @@ -255,4 +296,43 @@ namespace ts { return result; }; } + + /** + * Gets all property declarations with initializers on either the static or instance side of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to get properties from the static or instance side of the class. + */ + export function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): ReadonlyArray { + return filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty); + } + + /** + * Gets a value indicating whether a class element is a static property declaration with an initializer. + * + * @param member The class element node. + */ + export function isStaticInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } { + return isInitializedProperty(member) && hasStaticModifier(member); + } + + /** + * Gets a value indicating whether a class element is an instance property declaration with an initializer. + * + * @param member The class element node. + */ + export function isInstanceInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } { + return isInitializedProperty(member) && !hasStaticModifier(member); + } + + /** + * Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer. + * + * @param member The class element node. + * @param isStatic A value indicating whether the member should be a static or instance member. + */ + export function isInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } { + return member.kind === SyntaxKind.PropertyDeclaration + && (member).initializer !== undefined; + } } \ No newline at end of file diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index fdc0ff2969f..f5e16b0d127 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -30,6 +30,7 @@ "transformers/utilities.ts", "transformers/destructuring.ts", "transformers/ts.ts", + "transformers/classFields.ts", "transformers/es2017.ts", "transformers/es2018.ts", "transformers/es2019.ts", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 0e99b22a5a1..845c63b707b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5197,6 +5197,7 @@ namespace ts { ContainsYield = 1 << 17, ContainsHoistedDeclarationOrCompletion = 1 << 18, ContainsDynamicImport = 1 << 19, + ContainsClassFields = 1 << 20, // Please leave this as 1 << 29. // It is the maximum bit we can set before we outgrow the size of a v8 small integer (SMI) on an x86 system. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index b1ceee7979c..3d6c889986d 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -5188,6 +5188,9 @@ namespace ts { return node.parent.left.name; } } + else if (isVariableDeclaration(node.parent) && isIdentifier(node.parent.name)) { + return node.parent.name; + } } /** diff --git a/src/harness/client.ts b/src/harness/client.ts index d223f9f5fe3..4f8e84dcdaf 100644 --- a/src/harness/client.ts +++ b/src/harness/client.ts @@ -395,8 +395,15 @@ namespace ts.server { const locations: RenameLocation[] = []; for (const entry of body.locs) { const fileName = entry.file; - for (const { start, end, ...prefixSuffixText } of entry.locs) { - locations.push({ textSpan: this.decodeSpan({ start, end }, fileName), fileName, ...prefixSuffixText }); + for (const { start, end, contextStart, contextEnd, ...prefixSuffixText } of entry.locs) { + locations.push({ + textSpan: this.decodeSpan({ start, end }, fileName), + fileName, + ...(contextStart !== undefined ? + { contextSpan: this.decodeSpan({ start: contextStart, end: contextEnd! }, fileName) } : + undefined), + ...prefixSuffixText + }); } } diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 80fb27508d9..d7676176541 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -42,6 +42,7 @@ namespace FourSlash { * is a range with `text in range` "selected". */ ranges: Range[]; + rangesByText?: ts.MultiMap; } export interface Marker { @@ -955,12 +956,15 @@ namespace FourSlash { const fullExpected = ts.map(parts, ({ definition, ranges }) => ({ definition: typeof definition === "string" ? definition : { ...definition, range: ts.createTextSpanFromRange(definition.range) }, references: ranges.map(r => { - const { isWriteAccess = false, isDefinition = false, isInString } = (r.marker && r.marker.data || {}) as { isWriteAccess?: boolean, isDefinition?: boolean, isInString?: true }; + const { isWriteAccess = false, isDefinition = false, isInString, contextRangeIndex } = (r.marker && r.marker.data || {}) as { isWriteAccess?: boolean, isDefinition?: boolean, isInString?: true, contextRangeIndex?: number }; return { fileName: r.fileName, textSpan: ts.createTextSpanFromRange(r), isWriteAccess, isDefinition, + ...(contextRangeIndex !== undefined ? + { contextSpan: ts.createTextSpanFromRange(this.getRanges()[contextRangeIndex]) } : + undefined), ...(isInString ? { isInString: true } : undefined), }; }), @@ -997,8 +1001,8 @@ namespace FourSlash { assert.deepEqual | undefined>(refs, expected); } - public verifySingleReferenceGroup(definition: FourSlashInterface.ReferenceGroupDefinition, ranges?: Range[]) { - ranges = ranges || this.getRanges(); + public verifySingleReferenceGroup(definition: FourSlashInterface.ReferenceGroupDefinition, ranges?: Range[] | string) { + ranges = ts.isString(ranges) ? this.rangesByText().get(ranges)! : ranges || this.getRanges(); this.verifyReferenceGroups(ranges, [{ definition, ranges }]); } @@ -1011,7 +1015,7 @@ Actual: ${stringify(fullActual)}`); }; if ((actual === undefined) !== (expected === undefined)) { - fail(`Expected ${expected}, got ${actual}`); + fail(`Expected ${stringify(expected)}, got ${stringify(actual)}`); } for (const key in actual) { @@ -1021,7 +1025,7 @@ Actual: ${stringify(fullActual)}`); recur(ak, ek, path ? path + "." + key : key); } else if (ak !== ek) { - fail(`Expected '${key}' to be '${ek}', got '${ak}'`); + fail(`Expected '${key}' to be '${stringify(ek)}', got '${stringify(ak)}'`); } } } @@ -1189,7 +1193,15 @@ Actual: ${stringify(fullActual)}`); locations && ts.sort(locations, (r1, r2) => ts.compareStringsCaseSensitive(r1.fileName, r2.fileName) || r1.textSpan.start - r2.textSpan.start); assert.deepEqual(sort(references), sort(ranges.map((rangeOrOptions): ts.RenameLocation => { const { range, ...prefixSuffixText } = "range" in rangeOrOptions ? rangeOrOptions : { range: rangeOrOptions }; - return { fileName: range.fileName, textSpan: ts.createTextSpanFromRange(range), ...prefixSuffixText }; + const { contextRangeIndex } = (range.marker && range.marker.data || {}) as { contextRangeIndex?: number; }; + return { + fileName: range.fileName, + textSpan: ts.createTextSpanFromRange(range), + ...(contextRangeIndex !== undefined ? + { contextSpan: ts.createTextSpanFromRange(this.getRanges()[contextRangeIndex]) } : + undefined), + ...prefixSuffixText + }; }))); } } @@ -1844,6 +1856,7 @@ Actual: ${stringify(fullActual)}`); range.end = updatePosition(range.end, editStart, editEnd, newText); } } + this.testData.rangesByText = undefined; } private removeWhitespace(text: string): string { @@ -2026,7 +2039,9 @@ Actual: ${stringify(fullActual)}`); } public rangesByText(): ts.Map { + if (this.testData.rangesByText) return this.testData.rangesByText; const result = ts.createMultiMap(); + this.testData.rangesByText = result; for (const range of this.getRanges()) { const text = this.rangeText(range); result.add(text, range); @@ -2714,8 +2729,8 @@ Actual: ${stringify(fullActual)}`); return this.languageService.getDocumentHighlights(this.activeFile.fileName, this.currentCaretPosition, filesToSearch); } - public verifyRangesAreOccurrences(isWriteAccess?: boolean) { - const ranges = this.getRanges(); + public verifyRangesAreOccurrences(isWriteAccess?: boolean, ranges?: Range[]) { + ranges = ranges || this.getRanges(); for (const r of ranges) { this.goToRangeStart(r); this.verifyOccurrencesAtPositionListCount(ranges.length); @@ -2725,8 +2740,13 @@ Actual: ${stringify(fullActual)}`); } } - public verifyRangesWithSameTextAreRenameLocations() { - this.rangesByText().forEach(ranges => this.verifyRangesAreRenameLocations(ranges)); + public verifyRangesWithSameTextAreRenameLocations(...texts: string[]) { + if (texts.length) { + texts.forEach(text => this.verifyRangesAreRenameLocations(this.rangesByText().get(text))); + } + else { + this.rangesByText().forEach(ranges => this.verifyRangesAreRenameLocations(ranges)); + } } public verifyRangesWithSameTextAreDocumentHighlights() { @@ -3971,7 +3991,7 @@ namespace FourSlashInterface { this.state.verifyGetReferencesForServerTest(expected); } - public singleReferenceGroup(definition: ReferenceGroupDefinition, ranges?: FourSlash.Range[]) { + public singleReferenceGroup(definition: ReferenceGroupDefinition, ranges?: FourSlash.Range[] | string) { this.state.verifySingleReferenceGroup(definition, ranges); } @@ -4093,12 +4113,12 @@ namespace FourSlashInterface { this.state.verifyOccurrencesAtPositionListCount(expectedCount); } - public rangesAreOccurrences(isWriteAccess?: boolean) { - this.state.verifyRangesAreOccurrences(isWriteAccess); + public rangesAreOccurrences(isWriteAccess?: boolean, ranges?: FourSlash.Range[]) { + this.state.verifyRangesAreOccurrences(isWriteAccess, ranges); } - public rangesWithSameTextAreRenameLocations() { - this.state.verifyRangesWithSameTextAreRenameLocations(); + public rangesWithSameTextAreRenameLocations(...texts: string[]) { + this.state.verifyRangesWithSameTextAreRenameLocations(...texts); } public rangesAreRenameLocations(options?: FourSlash.Range[] | { findInStrings?: boolean, findInComments?: boolean, ranges?: FourSlash.Range[] }) { diff --git a/src/lib/dom.generated.d.ts b/src/lib/dom.generated.d.ts index 18f38b53560..e527838fc76 100644 --- a/src/lib/dom.generated.d.ts +++ b/src/lib/dom.generated.d.ts @@ -250,6 +250,15 @@ interface ConvolverOptions extends AudioNodeOptions { disableNormalization?: boolean; } +interface CredentialCreationOptions { + signal?: AbortSignal; +} + +interface CredentialRequestOptions { + mediation?: CredentialMediationRequirement; + signal?: AbortSignal; +} + interface CustomEventInit extends EventInit { detail?: T; } @@ -432,7 +441,6 @@ interface EventModifierInit extends UIEventInit { modifierFnLock?: boolean; modifierHyper?: boolean; modifierNumLock?: boolean; - modifierOS?: boolean; modifierScrollLock?: boolean; modifierSuper?: boolean; modifierSymbol?: boolean; @@ -546,6 +554,12 @@ interface ImageEncodeOptions { type?: string; } +interface InputEventInit extends UIEventInit { + data?: string | null; + inputType?: string; + isComposing?: boolean; +} + interface IntersectionObserverEntryInit { boundingClientRect: DOMRectInit; intersectionRatio: number; @@ -589,6 +603,7 @@ interface KeyAlgorithm { interface KeyboardEventInit extends EventModifierInit { code?: string; + isComposing?: boolean; key?: string; location?: number; repeat?: boolean; @@ -780,12 +795,33 @@ interface MultiCacheQueryOptions extends CacheQueryOptions { } interface MutationObserverInit { + /** + * Set to a list of attribute local names (without namespace) if not all attribute mutations need to be observed and attributes is true or omitted. + */ attributeFilter?: string[]; + /** + * Set to true if attributes is true or omitted and target's attribute value before the mutation needs to be recorded. + */ attributeOldValue?: boolean; + /** + * Set to true if mutations to target's attributes are to be observed. Can be omitted if attributeOldValue or attributeFilter is specified. + */ attributes?: boolean; + /** + * Set to true if mutations to target's data are to be observed. Can be omitted if characterDataOldValue is specified. + */ characterData?: boolean; + /** + * Set to true if characterData is set to true or omitted and target's data before the mutation needs to be recorded. + */ characterDataOldValue?: boolean; + /** + * Set to true if mutations to target's children are to be observed. + */ childList?: boolean; + /** + * Set to true if mutations to not just target, but also target's descendants are to be observed. + */ subtree?: boolean; } @@ -1390,18 +1426,57 @@ interface RegistrationOptions { } interface RequestInit { + /** + * A BodyInit object or null to set request's body. + */ body?: BodyInit | null; + /** + * A string indicating how the request will interact with the browser's cache to set request's cache. + */ cache?: RequestCache; + /** + * A string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. Sets request's credentials. + */ credentials?: RequestCredentials; + /** + * A Headers object, an object literal, or an array of two-item arrays to set request's headers. + */ headers?: HeadersInit; + /** + * A cryptographic hash of the resource to be fetched by request. Sets request's integrity. + */ integrity?: string; + /** + * A boolean to set request's keepalive. + */ keepalive?: boolean; + /** + * A string to set request's method. + */ method?: string; + /** + * A string to indicate whether the request will use CORS, or will be restricted to same-origin URLs. Sets request's mode. + */ mode?: RequestMode; + /** + * A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect. + */ redirect?: RequestRedirect; + /** + * A string whose value is a same-origin URL, "about:client", or the empty string, to set request's referrer. + */ referrer?: string; + /** + * A referrer policy to set request's referrerPolicy. + */ referrerPolicy?: ReferrerPolicy; + /** + * An AbortSignal to set request's signal. + */ signal?: AbortSignal | null; + /** + * Can only be null. Used to disassociate request from any Window. + */ window?: any; } @@ -1654,14 +1729,15 @@ interface WebAuthnExtensions { } interface WebGLContextAttributes { - alpha?: GLboolean; - antialias?: GLboolean; - depth?: GLboolean; + alpha?: boolean; + antialias?: boolean; + depth?: boolean; + desynchronized?: boolean; failIfMajorPerformanceCaveat?: boolean; powerPreference?: WebGLPowerPreference; - premultipliedAlpha?: GLboolean; - preserveDrawingBuffer?: GLboolean; - stencil?: GLboolean; + premultipliedAlpha?: boolean; + preserveDrawingBuffer?: boolean; + stencil?: boolean; } interface WebGLContextEventInit extends EventInit { @@ -1706,8 +1782,7 @@ interface AbortController { */ readonly signal: AbortSignal; /** - * Invoking this method will set this object's AbortSignal's aborted flag and - * signal to any observers that the associated activity is to be aborted. + * Invoking this method will set this object's AbortSignal's aborted flag and signal to any observers that the associated activity is to be aborted. */ abort(): void; } @@ -1724,8 +1799,7 @@ interface AbortSignalEventMap { /** A signal object that allows you to communicate with a DOM request (such as a Fetch) and abort it if required via an AbortController object. */ interface AbortSignal extends EventTarget { /** - * Returns true if this AbortSignal's AbortController has signaled to abort, and false - * otherwise. + * Returns true if this AbortSignal's AbortController has signaled to abort, and false otherwise. */ readonly aborted: boolean; onabort: ((this: AbortSignal, ev: Event) => any) | null; @@ -1741,10 +1815,25 @@ declare var AbortSignal: { }; interface AbstractRange { + /** + * Returns true if range is collapsed, and false otherwise. + */ readonly collapsed: boolean; + /** + * Returns range's end node. + */ readonly endContainer: Node; + /** + * Returns range's end offset. + */ readonly endOffset: number; + /** + * Returns range's start node. + */ readonly startContainer: Node; + /** + * Returns range's start offset. + */ readonly startOffset: number; } @@ -1854,6 +1943,11 @@ declare var AnimationEvent: { new(type: string, animationEventInitDict?: AnimationEventInit): AnimationEvent; }; +interface AnimationFrameProvider { + cancelAnimationFrame(handle: number): void; + requestAnimationFrame(callback: FrameRequestCallback): number; +} + interface AnimationPlaybackEvent extends Event { readonly currentTime: number | null; readonly timelineTime: number | null; @@ -2343,7 +2437,7 @@ declare var BroadcastChannel: { new(name: string): BroadcastChannel; }; -/** An interface of the Streams API provides a built-in byte length queuing strategy that can be used when constructing streams. */ +/** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ interface ByteLengthQueuingStrategy extends QueuingStrategy { highWaterMark: number; size(chunk: ArrayBufferView): number; @@ -2522,9 +2616,9 @@ declare var CSSRuleList: { /** An object that is a CSS declaration block, and exposes style information and various style-related methods and properties. */ interface CSSStyleDeclaration { - alignContent: string | null; - alignItems: string | null; - alignSelf: string | null; + alignContent: string; + alignItems: string; + alignSelf: string; alignmentBaseline: string | null; animation: string; animationDelay: string; @@ -2594,7 +2688,7 @@ interface CSSStyleDeclaration { clipPath: string | null; clipRule: string | null; color: string | null; - colorInterpolationFilters: string | null; + colorInterpolationFilters: string; columnCount: string; columnFill: string; columnGap: string; @@ -2611,7 +2705,7 @@ interface CSSStyleDeclaration { cssFloat: string | null; cssText: string; cursor: string; - direction: string | null; + direction: string; display: string | null; dominantBaseline: string | null; emptyCells: string | null; @@ -2619,7 +2713,7 @@ interface CSSStyleDeclaration { fill: string | null; fillOpacity: string | null; fillRule: string | null; - filter: string | null; + filter: string; flex: string | null; flexBasis: string | null; flexDirection: string | null; @@ -2627,20 +2721,27 @@ interface CSSStyleDeclaration { flexGrow: string | null; flexShrink: string | null; flexWrap: string | null; - floodColor: string | null; - floodOpacity: string | null; - font: string | null; - fontFamily: string | null; - fontFeatureSettings: string | null; - fontSize: string | null; - fontSizeAdjust: string | null; - fontStretch: string | null; - fontStyle: string | null; - fontVariant: string | null; - fontWeight: string | null; - gap: string | null; + floodColor: string; + floodOpacity: string; + font: string; + fontFamily: string; + fontFeatureSettings: string; + fontKerning: string; + fontSize: string; + fontSizeAdjust: string; + fontStretch: string; + fontStyle: string; + fontSynthesis: string; + fontVariant: string; + fontVariantCaps: string; + fontVariantEastAsian: string; + fontVariantLigatures: string; + fontVariantNumeric: string; + fontVariantPosition: string; + fontWeight: string; + gap: string; glyphOrientationHorizontal: string | null; - glyphOrientationVertical: string | null; + glyphOrientationVertical: string; grid: string | null; gridArea: string | null; gridAutoColumns: string | null; @@ -2648,24 +2749,25 @@ interface CSSStyleDeclaration { gridAutoRows: string | null; gridColumn: string | null; gridColumnEnd: string | null; - gridColumnGap: string | null; + gridColumnGap: string; gridColumnStart: string | null; - gridGap: string | null; + gridGap: string; gridRow: string | null; gridRowEnd: string | null; - gridRowGap: string | null; + gridRowGap: string; gridRowStart: string | null; gridTemplate: string | null; gridTemplateAreas: string | null; gridTemplateColumns: string | null; gridTemplateRows: string | null; height: string | null; + hyphens: string; imageOrientation: string; imageRendering: string; imeMode: string | null; - justifyContent: string | null; - justifyItems: string | null; - justifySelf: string | null; + justifyContent: string; + justifyItems: string; + justifySelf: string; kerning: string | null; layoutGrid: string | null; layoutGridChar: string | null; @@ -2674,9 +2776,9 @@ interface CSSStyleDeclaration { layoutGridType: string | null; left: string | null; readonly length: number; - letterSpacing: string | null; - lightingColor: string | null; - lineBreak: string | null; + letterSpacing: string; + lightingColor: string; + lineBreak: string; lineHeight: string | null; listStyle: string | null; listStyleImage: string | null; @@ -2755,6 +2857,8 @@ interface CSSStyleDeclaration { outlineStyle: string; outlineWidth: string; overflow: string | null; + overflowAnchor: string; + overflowWrap: string; overflowX: string | null; overflowY: string | null; padding: string | null; @@ -2769,13 +2873,16 @@ interface CSSStyleDeclaration { penAction: string | null; perspective: string | null; perspectiveOrigin: string | null; + placeContent: string; + placeItems: string; + placeSelf: string; pointerEvents: string | null; position: string | null; quotes: string | null; - resize: string | null; + resize: string; right: string | null; rotate: string | null; - rowGap: string | null; + rowGap: string; rubyAlign: string | null; rubyOverhang: string | null; rubyPosition: string | null; @@ -2791,24 +2898,34 @@ interface CSSStyleDeclaration { strokeMiterlimit: string | null; strokeOpacity: string | null; strokeWidth: string | null; + tabSize: string; tableLayout: string | null; - textAlign: string | null; - textAlignLast: string | null; + textAlign: string; + textAlignLast: string; textAnchor: string | null; - textCombineUpright: string | null; - textDecoration: string | null; - textIndent: string | null; - textJustify: string | null; + textCombineUpright: string; + textDecoration: string; + textDecorationColor: string; + textDecorationLine: string; + textDecorationStyle: string; + textEmphasis: string; + textEmphasisColor: string; + textEmphasisPosition: string; + textEmphasisStyle: string; + textIndent: string; + textJustify: string; textKashida: string | null; textKashidaSpace: string | null; + textOrientation: string; textOverflow: string; - textShadow: string | null; - textTransform: string | null; - textUnderlinePosition: string | null; + textShadow: string; + textTransform: string; + textUnderlinePosition: string; top: string | null; touchAction: string; - transform: string | null; - transformOrigin: string | null; + transform: string; + transformBox: string; + transformOrigin: string; transformStyle: string | null; transition: string; transitionDelay: string; @@ -2816,8 +2933,8 @@ interface CSSStyleDeclaration { transitionProperty: string; transitionTimingFunction: string; translate: string | null; - unicodeBidi: string | null; - userSelect: string | null; + unicodeBidi: string; + userSelect: string; verticalAlign: string | null; visibility: string | null; /** @deprecated */ @@ -2973,14 +3090,14 @@ interface CSSStyleDeclaration { webkitUserModify: string | null; webkitUserSelect: string | null; webkitWritingMode: string | null; - whiteSpace: string | null; + whiteSpace: string; widows: string | null; width: string | null; willChange: string; - wordBreak: string | null; - wordSpacing: string | null; - wordWrap: string | null; - writingMode: string | null; + wordBreak: string; + wordSpacing: string; + wordWrap: string; + writingMode: string; zIndex: string | null; zoom: string | null; getPropertyPriority(propertyName: string): string; @@ -3124,11 +3241,9 @@ interface CanvasFilters { /** An opaque object describing a gradient. It is returned by the methods CanvasRenderingContext2D.createLinearGradient() or CanvasRenderingContext2D.createRadialGradient(). */ interface CanvasGradient { /** - * Adds a color stop with the given color to the gradient at the given offset. 0.0 is the offset - * at one end of the gradient, 1.0 is the offset at the other end. - * Throws an "IndexSizeError" DOMException if the offset - * is out of range. Throws a "SyntaxError" DOMException if - * the color cannot be parsed. + * Adds a color stop with the given color to the gradient at the given offset. 0.0 is the offset at one end of the gradient, 1.0 is the offset at the other end. + * + * Throws an "IndexSizeError" DOMException if the offset is out of range. Throws a "SyntaxError" DOMException if the color cannot be parsed. */ addColorStop(offset: number, color: string): void; } @@ -3176,8 +3291,7 @@ interface CanvasPathDrawingStyles { /** An opaque object describing a pattern, based on an image, a canvas, or a video, created by the CanvasRenderingContext2D.createPattern() method. */ interface CanvasPattern { /** - * Sets the transformation matrix that will be used when rendering the pattern during a fill or - * stroke painting operation. + * Sets the transformation matrix that will be used when rendering the pattern during a fill or stroke painting operation. */ setTransform(transform?: DOMMatrix2DInit): void; } @@ -3294,14 +3408,14 @@ declare var CharacterData: { interface ChildNode extends Node { /** * Inserts nodes just after node, while replacing strings in nodes with equivalent Text nodes. - * Throws a "HierarchyRequestError" DOMException if the constraints of - * the node tree are violated. + * + * Throws a "HierarchyRequestError" DOMException if the constraints of the node tree are violated. */ after(...nodes: (Node | string)[]): void; /** * Inserts nodes just before node, while replacing strings in nodes with equivalent Text nodes. - * Throws a "HierarchyRequestError" DOMException if the constraints of - * the node tree are violated. + * + * Throws a "HierarchyRequestError" DOMException if the constraints of the node tree are violated. */ before(...nodes: (Node | string)[]): void; /** @@ -3310,8 +3424,8 @@ interface ChildNode extends Node { remove(): void; /** * Replaces node with nodes, while replacing strings in nodes with equivalent Text nodes. - * Throws a "HierarchyRequestError" DOMException if the constraints of - * the node tree are violated. + * + * Throws a "HierarchyRequestError" DOMException if the constraints of the node tree are violated. */ replaceWith(...nodes: (Node | string)[]): void; } @@ -3387,13 +3501,11 @@ declare var Comment: { /** The DOM CompositionEvent represents events that occur due to the user indirectly entering text. */ interface CompositionEvent extends UIEvent { readonly data: string; - readonly locale: string; - initCompositionEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, dataArg: string, locale: string): void; } declare var CompositionEvent: { prototype: CompositionEvent; - new(typeArg: string, eventInitDict?: CompositionEventInit): CompositionEvent; + new(type: string, eventInitDict?: CompositionEventInit): CompositionEvent; }; interface ConcatParams extends Algorithm { @@ -3474,7 +3586,7 @@ interface Coordinates { readonly speed: number | null; } -/** An interface of the Streams API provides a built-in byte length queuing strategy that can be used when constructing streams. */ +/** This Streams API interface provides a built-in byte length queuing strategy that can be used when constructing streams. */ interface CountQueuingStrategy extends QueuingStrategy { highWaterMark: number; size(chunk: any): 1; @@ -3485,6 +3597,28 @@ declare var CountQueuingStrategy: { new(options: { highWaterMark: number }): CountQueuingStrategy; }; +interface Credential { + readonly id: string; + readonly type: string; +} + +declare var Credential: { + prototype: Credential; + new(): Credential; +}; + +interface CredentialsContainer { + create(options?: CredentialCreationOptions): Promise; + get(options?: CredentialRequestOptions): Promise; + preventSilentAccess(): Promise; + store(credential: Credential): Promise; +} + +declare var CredentialsContainer: { + prototype: CredentialsContainer; + new(): CredentialsContainer; +}; + /** Basic cryptography features available in the current context. It allows access to a cryptographically strong random number generator and to cryptographic primitives. */ interface Crypto { readonly subtle: SubtleCrypto; @@ -3534,8 +3668,7 @@ declare var CustomElementRegistry: { interface CustomEvent extends Event { /** - * Returns any custom data event was created with. - * Typically used for synthetic events. + * Returns any custom data event was created with. Typically used for synthetic events. */ readonly detail: T; initCustomEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, detailArg: T): void; @@ -3859,8 +3992,7 @@ interface DOMStringList { */ readonly length: number; /** - * Returns true if strings contains string, and false - * otherwise. + * Returns true if strings contains string, and false otherwise. */ contains(string: string): boolean; /** @@ -3893,15 +4025,16 @@ interface DOMTokenList { readonly length: number; /** * Returns the associated set as string. + * * Can be set, to change the associated attribute. */ value: string; /** * Adds all arguments passed, except those already present. - * Throws a "SyntaxError" DOMException if one of the arguments is the empty - * string. - * Throws an "InvalidCharacterError" DOMException if one of the arguments - * contains any ASCII whitespace. + * + * Throws a "SyntaxError" DOMException if one of the arguments is the empty string. + * + * Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. */ add(...tokens: string[]): void; /** @@ -3909,32 +4042,42 @@ interface DOMTokenList { */ contains(token: string): boolean; /** - * tokenlist[index] + * Returns the token with index index. */ item(index: number): string | null; /** * Removes arguments passed, if they are present. - * Throws a "SyntaxError" DOMException if one of the arguments is the empty - * string. - * Throws an "InvalidCharacterError" DOMException if one of the arguments - * contains any ASCII whitespace. + * + * Throws a "SyntaxError" DOMException if one of the arguments is the empty string. + * + * Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. */ remove(...tokens: string[]): void; /** * Replaces token with newToken. + * * Returns true if token was replaced with newToken, and false otherwise. - * Throws a "SyntaxError" DOMException if one of the arguments is the empty - * string. - * Throws an "InvalidCharacterError" DOMException if one of the arguments - * contains any ASCII whitespace. + * + * Throws a "SyntaxError" DOMException if one of the arguments is the empty string. + * + * Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. */ replace(oldToken: string, newToken: string): void; /** - * Returns true if token is in the associated attribute's supported tokens. Returns - * false otherwise. + * Returns true if token is in the associated attribute's supported tokens. Returns false otherwise. + * * Throws a TypeError if the associated attribute has no supported tokens defined. */ supports(token: string): boolean; + /** + * If force is not given, "toggles" token, removing it if it's present and adding it if it's not present. If force is true, adds token (same as add()). If force is false, removes token (same as remove()). + * + * Returns true if token is now present, and false otherwise. + * + * Throws a "SyntaxError" DOMException if token is empty. + * + * Throws an "InvalidCharacterError" DOMException if token contains any spaces. + */ toggle(token: string, force?: boolean): boolean; forEach(callbackfn: (value: string, key: number, parent: DOMTokenList) => void, thisArg?: any): void; [index: number]: string; @@ -3960,7 +4103,21 @@ declare var DataCue: { /** Used to hold the data that is being dragged during a drag and drop operation. It may hold one or more data items, each of one or more data types. For more information about drag and drop, see HTML Drag and Drop API. */ interface DataTransfer { + /** + * Returns the kind of operation that is currently selected. If the kind of operation isn't one of those that is allowed by the effectAllowed attribute, then the operation will fail. + * + * Can be set, to change the selected operation. + * + * The possible values are "none", "copy", "link", and "move". + */ dropEffect: string; + /** + * Returns the kinds of operations that are to be allowed. + * + * Can be set (during the dragstart event), to change the allowed operations. + * + * The possible values are "none", "copy", "copyLink", "copyMove", "link", "linkMove", "move", "all", and "uninitialized", + */ effectAllowed: string; /** * Returns a FileList of the files being dragged, if any. @@ -3971,8 +4128,7 @@ interface DataTransfer { */ readonly items: DataTransferItemList; /** - * Returns a frozen array listing the formats that were set in the dragstart event. In addition, if any files are being - * dragged, then one of the types will be the string "Files". + * Returns a frozen array listing the formats that were set in the dragstart event. In addition, if any files are being dragged, then one of the types will be the string "Files". */ readonly types: ReadonlyArray; /** @@ -3988,8 +4144,7 @@ interface DataTransfer { */ setData(format: string, data: string): void; /** - * Uses the given element to update the drag feedback, replacing any previously specified - * feedback. + * Uses the given element to update the drag feedback, replacing any previously specified feedback. */ setDragImage(image: Element, x: number, y: number): void; } @@ -4002,8 +4157,7 @@ declare var DataTransfer: { /** One drag data item. During a drag operation, each drag event has a dataTransfer property which contains a list of drag data items. Each item in the list is a DataTransferItem object. */ interface DataTransferItem { /** - * Returns the drag data item kind, one of: "string", - * "file". + * Returns the drag data item kind, one of: "string", "file". */ readonly kind: string; /** @@ -4015,8 +4169,7 @@ interface DataTransferItem { */ getAsFile(): File | null; /** - * Invokes the callback with the string data as the argument, if the drag data item - * kind is Plain Unicode string. + * Invokes the callback with the string data as the argument, if the drag data item kind is Plain Unicode string. */ getAsString(callback: FunctionStringCallback | null): void; webkitGetAsEntry(): any; @@ -4034,9 +4187,7 @@ interface DataTransferItemList { */ readonly length: number; /** - * Adds a new entry for the given data to the drag data store. If the data is plain - * text then a type string has to be provided - * also. + * Adds a new entry for the given data to the drag data store. If the data is plain text then a type string has to be provided also. */ add(data: string, type: string): DataTransferItem | null; add(data: File): DataTransferItem | null; @@ -4182,53 +4333,53 @@ interface DocumentEventMap extends GlobalEventHandlersEventMap, DocumentAndEleme /** Any web page loaded in the browser and serves as an entry point into the web page's content, which is the DOM tree. */ interface Document extends Node, NonElementParentNode, DocumentOrShadowRoot, ParentNode, XPathEvaluatorBase, GlobalEventHandlers, DocumentAndElementEventHandlers { - /** - * Sets or gets the URL for the current document. + /** + * Sets or gets the URL for the current document. */ readonly URL: string; - /** - * Gets the object that has the focus when the parent document has focus. + /** + * Gets the object that has the focus when the parent document has focus. */ readonly activeElement: Element | null; - /** - * Sets or gets the color of all active links in the document. + /** + * Sets or gets the color of all active links in the document. */ /** @deprecated */ alinkColor: string; - /** - * Returns a reference to the collection of elements contained by the object. + /** + * Returns a reference to the collection of elements contained by the object. */ /** @deprecated */ readonly all: HTMLAllCollection; - /** - * Retrieves a collection of all a objects that have a name and/or id property. Objects in this collection are in HTML source order. + /** + * Retrieves a collection of all a objects that have a name and/or id property. Objects in this collection are in HTML source order. */ /** @deprecated */ readonly anchors: HTMLCollectionOf; - /** - * Retrieves a collection of all applet objects in the document. + /** + * Retrieves a collection of all applet objects in the document. */ /** @deprecated */ readonly applets: HTMLCollectionOf; - /** - * Deprecated. Sets or retrieves a value that indicates the background color behind the object. + /** + * Deprecated. Sets or retrieves a value that indicates the background color behind the object. */ /** @deprecated */ bgColor: string; - /** - * Specifies the beginning and end of the document body. + /** + * Specifies the beginning and end of the document body. */ body: HTMLElement; /** * Returns document's encoding. */ readonly characterSet: string; - /** - * Gets or sets the character set used to encode the object. + /** + * Gets or sets the character set used to encode the object. */ readonly charset: string; - /** - * Gets a value that indicates whether standards-compliant mode is switched on for the object. + /** + * Gets a value that indicates whether standards-compliant mode is switched on for the object. */ readonly compatMode: string; /** @@ -4236,69 +4387,61 @@ interface Document extends Node, NonElementParentNode, DocumentOrShadowRoot, Par */ readonly contentType: string; /** - * Returns the HTTP cookies that apply to the Document. If there are no cookies or - * cookies can't be applied to this resource, the empty string will be returned. + * Returns the HTTP cookies that apply to the Document. If there are no cookies or cookies can't be applied to this resource, the empty string will be returned. + * * Can be set, to add a new cookie to the element's set of HTTP cookies. - * If the contents are sandboxed into a - * unique origin (e.g. in an iframe with the sandbox attribute), a - * "SecurityError" DOMException will be thrown on getting - * and setting. + * + * If the contents are sandboxed into a unique origin (e.g. in an iframe with the sandbox attribute), a "SecurityError" DOMException will be thrown on getting and setting. */ cookie: string; /** - * Returns the script element, or the SVG script element, - * that is currently executing, as long as the element represents a classic script. - * In the case of reentrant script execution, returns the one that most recently started executing - * amongst those that have not yet finished executing. - * Returns null if the Document is not currently executing a script - * or SVG script element (e.g., because the running script is an event - * handler, or a timeout), or if the currently executing script or SVG - * script element represents a module script. + * Returns the script element, or the SVG script element, that is currently executing, as long as the element represents a classic script. In the case of reentrant script execution, returns the one that most recently started executing amongst those that have not yet finished executing. + * + * Returns null if the Document is not currently executing a script or SVG script element (e.g., because the running script is an event handler, or a timeout), or if the currently executing script or SVG script element represents a module script. */ readonly currentScript: HTMLOrSVGScriptElement | null; readonly defaultView: WindowProxy | null; - /** - * Sets or gets a value that indicates whether the document can be edited. + /** + * Sets or gets a value that indicates whether the document can be edited. */ designMode: string; - /** - * Sets or retrieves a value that indicates the reading order of the object. + /** + * Sets or retrieves a value that indicates the reading order of the object. */ dir: string; - /** - * Gets an object representing the document type declaration associated with the current document. + /** + * Gets an object representing the document type declaration associated with the current document. */ readonly doctype: DocumentType | null; - /** - * Gets a reference to the root node of the document. + /** + * Gets a reference to the root node of the document. */ readonly documentElement: HTMLElement; /** * Returns document's URL. */ readonly documentURI: string; - /** - * Sets or gets the security domain of the document. + /** + * Sets or gets the security domain of the document. */ domain: string; - /** - * Retrieves a collection of all embed objects in the document. + /** + * Retrieves a collection of all embed objects in the document. */ readonly embeds: HTMLCollectionOf; - /** - * Sets or gets the foreground (text) color of the document. + /** + * Sets or gets the foreground (text) color of the document. */ /** @deprecated */ fgColor: string; - /** - * Retrieves a collection, in source order, of all form objects in the document. + /** + * Retrieves a collection, in source order, of all form objects in the document. */ readonly forms: HTMLCollectionOf; /** @deprecated */ readonly fullscreen: boolean; /** - * Returns true if document has the ability to display elements fullscreen - * and fullscreen is supported, or false otherwise. + * Returns true if document has the ability to display elements fullscreen and fullscreen is supported, or false otherwise. */ readonly fullscreenEnabled: boolean; /** @@ -4306,42 +4449,42 @@ interface Document extends Node, NonElementParentNode, DocumentOrShadowRoot, Par */ readonly head: HTMLHeadElement; readonly hidden: boolean; - /** - * Retrieves a collection, in source order, of img objects in the document. + /** + * Retrieves a collection, in source order, of img objects in the document. */ readonly images: HTMLCollectionOf; - /** - * Gets the implementation object of the current document. + /** + * Gets the implementation object of the current document. */ readonly implementation: DOMImplementation; - /** - * Returns the character encoding used to create the webpage that is loaded into the document object. + /** + * Returns the character encoding used to create the webpage that is loaded into the document object. */ readonly inputEncoding: string; - /** - * Gets the date that the page was last modified, if the page supplies one. + /** + * Gets the date that the page was last modified, if the page supplies one. */ readonly lastModified: string; - /** - * Sets or gets the color of the document links. + /** + * Sets or gets the color of the document links. */ /** @deprecated */ linkColor: string; - /** - * Retrieves a collection of all a objects that specify the href property and all area objects in the document. + /** + * Retrieves a collection of all a objects that specify the href property and all area objects in the document. */ readonly links: HTMLCollectionOf; - /** - * Contains information about the current URL. + /** + * Contains information about the current URL. */ location: Location; onfullscreenchange: ((this: Document, ev: Event) => any) | null; onfullscreenerror: ((this: Document, ev: Event) => any) | null; onpointerlockchange: ((this: Document, ev: Event) => any) | null; onpointerlockerror: ((this: Document, ev: Event) => any) | null; - /** - * Fires when the state of the object has changed. - * @param ev The event + /** + * Fires when the state of the object has changed. + * @param ev The event */ onreadystatechange: ((this: Document, ev: ProgressEvent) => any) | null; onvisibilitychange: ((this: Document, ev: Event) => any) | null; @@ -4353,34 +4496,34 @@ interface Document extends Node, NonElementParentNode, DocumentOrShadowRoot, Par * Return an HTMLCollection of the embed elements in the Document. */ readonly plugins: HTMLCollectionOf; - /** - * Retrieves a value that indicates the current state of the object. + /** + * Retrieves a value that indicates the current state of the object. */ readonly readyState: DocumentReadyState; - /** - * Gets the URL of the location that referred the user to the current page. + /** + * Gets the URL of the location that referred the user to the current page. */ readonly referrer: string; - /** - * Retrieves a collection of all script objects in the document. + /** + * Retrieves a collection of all script objects in the document. */ readonly scripts: HTMLCollectionOf; readonly scrollingElement: Element | null; readonly timeline: DocumentTimeline; - /** - * Contains the title of the document. + /** + * Contains the title of the document. */ title: string; readonly visibilityState: VisibilityState; - /** - * Sets or gets the color of the links that the user has visited. + /** + * Sets or gets the color of the links that the user has visited. */ /** @deprecated */ vlinkColor: string; /** * Moves node from another document and returns it. - * If node is a document, throws a "NotSupportedError" DOMException or, if node is a shadow root, throws a - * "HierarchyRequestError" DOMException. + * + * If node is a document, throws a "NotSupportedError" DOMException or, if node is a shadow root, throws a "HierarchyRequestError" DOMException. */ adoptNode(source: T): T; /** @deprecated */ @@ -4390,13 +4533,13 @@ interface Document extends Node, NonElementParentNode, DocumentOrShadowRoot, Par caretRangeFromPoint(x: number, y: number): Range; /** @deprecated */ clear(): void; - /** - * Closes an output stream and forces the sent data to display. + /** + * Closes an output stream and forces the sent data to display. */ close(): void; - /** - * Creates an attribute object with a specified name. - * @param name String that sets the attribute object's name. + /** + * Creates an attribute object with a specified name. + * @param name String that sets the attribute object's name. */ createAttribute(localName: string): Attr; createAttributeNS(namespace: string | null, qualifiedName: string): Attr; @@ -4404,35 +4547,36 @@ interface Document extends Node, NonElementParentNode, DocumentOrShadowRoot, Par * Returns a CDATASection node whose data is data. */ createCDATASection(data: string): CDATASection; - /** - * Creates a comment object with the specified data. - * @param data Sets the comment object's data. + /** + * Creates a comment object with the specified data. + * @param data Sets the comment object's data. */ createComment(data: string): Comment; - /** - * Creates a new document. + /** + * Creates a new document. */ createDocumentFragment(): DocumentFragment; - /** - * Creates an instance of the element for the specified tag. - * @param tagName The name of an element. + /** + * Creates an instance of the element for the specified tag. + * @param tagName The name of an element. */ createElement(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; /** @deprecated */ createElement(tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K]; createElement(tagName: string, options?: ElementCreationOptions): HTMLElement; /** - * Returns an element with namespace namespace. Its namespace prefix will be everything before ":" (U+003E) in qualifiedName or null. Its local name will be everything after - * ":" (U+003E) in qualifiedName or qualifiedName. - * If localName does not match the Name production an - * "InvalidCharacterError" DOMException will be thrown. + * Returns an element with namespace namespace. Its namespace prefix will be everything before ":" (U+003E) in qualifiedName or null. Its local name will be everything after ":" (U+003E) in qualifiedName or qualifiedName. + * + * If localName does not match the Name production an "InvalidCharacterError" DOMException will be thrown. + * * If one of the following conditions is true a "NamespaceError" DOMException will be thrown: + * * localName does not match the QName production. * Namespace prefix is not null and namespace is the empty string. * Namespace prefix is "xml" and namespace is not the XML namespace. * qualifiedName or namespace prefix is "xmlns" and namespace is not the XMLNS namespace. - * namespace is the XMLNS namespace and - * neither qualifiedName nor namespace prefix is "xmlns". + * namespace is the XMLNS namespace and neither qualifiedName nor namespace prefix is "xmlns". + * * When supplied, options's is can be used to create a customized built-in element. */ createElementNS(namespaceURI: "http://www.w3.org/1999/xhtml", qualifiedName: string): HTMLElement; @@ -4455,11 +4599,13 @@ interface Document extends Node, NonElementParentNode, DocumentOrShadowRoot, Par createEvent(eventInterface: "ErrorEvent"): ErrorEvent; createEvent(eventInterface: "Event"): Event; createEvent(eventInterface: "Events"): Event; + createEvent(eventInterface: "FileReaderProgressEvent"): FileReaderProgressEvent; createEvent(eventInterface: "FocusEvent"): FocusEvent; createEvent(eventInterface: "FocusNavigationEvent"): FocusNavigationEvent; createEvent(eventInterface: "GamepadEvent"): GamepadEvent; createEvent(eventInterface: "HashChangeEvent"): HashChangeEvent; createEvent(eventInterface: "IDBVersionChangeEvent"): IDBVersionChangeEvent; + createEvent(eventInterface: "InputEvent"): InputEvent; createEvent(eventInterface: "KeyboardEvent"): KeyboardEvent; createEvent(eventInterface: "ListeningStateChangedEvent"): ListeningStateChangedEvent; createEvent(eventInterface: "MSGestureEvent"): MSGestureEvent; @@ -4518,152 +4664,147 @@ interface Document extends Node, NonElementParentNode, DocumentOrShadowRoot, Par createEvent(eventInterface: "WebGLContextEvent"): WebGLContextEvent; createEvent(eventInterface: "WheelEvent"): WheelEvent; createEvent(eventInterface: string): Event; - /** - * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document. - * @param root The root element or node to start traversing on. - * @param whatToShow The type of nodes or elements to appear in the node list - * @param filter A custom NodeFilter function to use. For more information, see filter. Use null for no filter. - * @param entityReferenceExpansion A flag that specifies whether entity reference nodes are expanded. + /** + * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document. + * @param root The root element or node to start traversing on. + * @param whatToShow The type of nodes or elements to appear in the node list + * @param filter A custom NodeFilter function to use. For more information, see filter. Use null for no filter. + * @param entityReferenceExpansion A flag that specifies whether entity reference nodes are expanded. */ createNodeIterator(root: Node, whatToShow?: number, filter?: NodeFilter | null): NodeIterator; /** - * Returns a ProcessingInstruction node whose target is target and data is data. - * If target does not match the Name production an - * "InvalidCharacterError" DOMException will be thrown. - * If data contains "?>" an - * "InvalidCharacterError" DOMException will be thrown. + * Returns a ProcessingInstruction node whose target is target and data is data. If target does not match the Name production an "InvalidCharacterError" DOMException will be thrown. If data contains "?>" an "InvalidCharacterError" DOMException will be thrown. */ createProcessingInstruction(target: string, data: string): ProcessingInstruction; - /** - * Returns an empty range object that has both of its boundary points positioned at the beginning of the document. + /** + * Returns an empty range object that has both of its boundary points positioned at the beginning of the document. */ createRange(): Range; - /** - * Creates a text string from the specified value. - * @param data String that specifies the nodeValue property of the text node. + /** + * Creates a text string from the specified value. + * @param data String that specifies the nodeValue property of the text node. */ createTextNode(data: string): Text; - createTouch(view: WindowProxy, target: EventTarget, identifier: number, pageX: number, pageY: number, screenX: number, screenY: number): Touch; - createTouchList(...touches: Touch[]): TouchList; - /** - * Creates a TreeWalker object that you can use to traverse filtered lists of nodes or elements in a document. - * @param root The root element or node to start traversing on. - * @param whatToShow The type of nodes or elements to appear in the node list. For more information, see whatToShow. - * @param filter A custom NodeFilter function to use. - * @param entityReferenceExpansion A flag that specifies whether entity reference nodes are expanded. + /** + * Creates a TreeWalker object that you can use to traverse filtered lists of nodes or elements in a document. + * @param root The root element or node to start traversing on. + * @param whatToShow The type of nodes or elements to appear in the node list. For more information, see whatToShow. + * @param filter A custom NodeFilter function to use. + * @param entityReferenceExpansion A flag that specifies whether entity reference nodes are expanded. */ createTreeWalker(root: Node, whatToShow?: number, filter?: NodeFilter | null): TreeWalker; /** @deprecated */ createTreeWalker(root: Node, whatToShow: number, filter: NodeFilter | null, entityReferenceExpansion?: boolean): TreeWalker; - /** - * Returns the element for the specified x coordinate and the specified y coordinate. - * @param x The x-offset - * @param y The y-offset + /** + * Returns the element for the specified x coordinate and the specified y coordinate. + * @param x The x-offset + * @param y The y-offset */ elementFromPoint(x: number, y: number): Element | null; elementsFromPoint(x: number, y: number): Element[]; - /** - * Executes a command on the current document, current selection, or the given range. - * @param commandId String that specifies the command to execute. This command can be any of the command identifiers that can be executed in script. - * @param showUI Display the user interface, defaults to false. - * @param value Value to assign. + /** + * Executes a command on the current document, current selection, or the given range. + * @param commandId String that specifies the command to execute. This command can be any of the command identifiers that can be executed in script. + * @param showUI Display the user interface, defaults to false. + * @param value Value to assign. */ execCommand(commandId: string, showUI?: boolean, value?: string): boolean; /** - * Stops document's fullscreen element from being displayed fullscreen and - * resolves promise when done. + * Stops document's fullscreen element from being displayed fullscreen and resolves promise when done. */ exitFullscreen(): Promise; exitPointerLock(): void; getAnimations(): Animation[]; - /** - * Returns a reference to the first object with the specified value of the ID or NAME attribute. - * @param elementId String that specifies the ID value. Case-insensitive. + /** + * Returns a reference to the first object with the specified value of the ID or NAME attribute. + * @param elementId String that specifies the ID value. Case-insensitive. */ getElementById(elementId: string): HTMLElement | null; /** - * collection = element . getElementsByClassName(classNames) + * Returns a HTMLCollection of the elements in the object on which the method was invoked (a document or an element) that have all the classes given by classNames. The classNames argument is interpreted as a space-separated list of classes. */ getElementsByClassName(classNames: string): HTMLCollectionOf; - /** - * Gets a collection of objects based on the value of the NAME or ID attribute. - * @param elementName Gets a collection of objects based on the value of the NAME or ID attribute. + /** + * Gets a collection of objects based on the value of the NAME or ID attribute. + * @param elementName Gets a collection of objects based on the value of the NAME or ID attribute. */ getElementsByName(elementName: string): NodeListOf; - /** - * Retrieves a collection of objects based on the specified element name. - * @param name Specifies the name of an element. + /** + * Retrieves a collection of objects based on the specified element name. + * @param name Specifies the name of an element. */ getElementsByTagName(qualifiedName: K): HTMLCollectionOf; getElementsByTagName(qualifiedName: K): HTMLCollectionOf; getElementsByTagName(qualifiedName: string): HTMLCollectionOf; /** - * If namespace and localName are - * "*" returns a HTMLCollection of all descendant elements. + * If namespace and localName are "*" returns a HTMLCollection of all descendant elements. + * * If only namespace is "*" returns a HTMLCollection of all descendant elements whose local name is localName. + * * If only localName is "*" returns a HTMLCollection of all descendant elements whose namespace is namespace. + * * Otherwise, returns a HTMLCollection of all descendant elements whose namespace is namespace and local name is localName. */ getElementsByTagNameNS(namespaceURI: "http://www.w3.org/1999/xhtml", localName: string): HTMLCollectionOf; getElementsByTagNameNS(namespaceURI: "http://www.w3.org/2000/svg", localName: string): HTMLCollectionOf; getElementsByTagNameNS(namespaceURI: string, localName: string): HTMLCollectionOf; - /** - * Returns an object representing the current selection of the document that is loaded into the object displaying a webpage. + /** + * Returns an object representing the current selection of the document that is loaded into the object displaying a webpage. */ getSelection(): Selection | null; - /** - * Gets a value indicating whether the object currently has focus. + /** + * Gets a value indicating whether the object currently has focus. */ hasFocus(): boolean; /** * Returns a copy of node. If deep is true, the copy also includes the node's descendants. - * If node is a document or a shadow root, throws a - * "NotSupportedError" DOMException. + * + * If node is a document or a shadow root, throws a "NotSupportedError" DOMException. */ importNode(importedNode: T, deep: boolean): T; - /** - * Opens a new window and loads a document specified by a given URL. Also, opens a new window that uses the url parameter and the name parameter to collect the output of the write method and the writeln method. - * @param url Specifies a MIME type for the document. - * @param name Specifies the name of the window. This name is used as the value for the TARGET attribute on a form or an anchor element. - * @param features Contains a list of items separated by commas. Each item consists of an option and a value, separated by an equals sign (for example, "fullscreen=yes, toolbar=yes"). The following values are supported. - * @param replace Specifies whether the existing entry for the document is replaced in the history list. + /** + * Opens a new window and loads a document specified by a given URL. Also, opens a new window that uses the url parameter and the name parameter to collect the output of the write method and the writeln method. + * @param url Specifies a MIME type for the document. + * @param name Specifies the name of the window. This name is used as the value for the TARGET attribute on a form or an anchor element. + * @param features Contains a list of items separated by commas. Each item consists of an option and a value, separated by an equals sign (for example, "fullscreen=yes, toolbar=yes"). The following values are supported. + * @param replace Specifies whether the existing entry for the document is replaced in the history list. */ open(url?: string, name?: string, features?: string, replace?: boolean): Document; - /** - * Returns a Boolean value that indicates whether a specified command can be successfully executed using execCommand, given the current state of the document. - * @param commandId Specifies a command identifier. + /** + * Returns a Boolean value that indicates whether a specified command can be successfully executed using execCommand, given the current state of the document. + * @param commandId Specifies a command identifier. */ queryCommandEnabled(commandId: string): boolean; - /** - * Returns a Boolean value that indicates whether the specified command is in the indeterminate state. - * @param commandId String that specifies a command identifier. + /** + * Returns a Boolean value that indicates whether the specified command is in the indeterminate state. + * @param commandId String that specifies a command identifier. */ queryCommandIndeterm(commandId: string): boolean; - /** - * Returns a Boolean value that indicates the current state of the command. - * @param commandId String that specifies a command identifier. + /** + * Returns a Boolean value that indicates the current state of the command. + * @param commandId String that specifies a command identifier. */ queryCommandState(commandId: string): boolean; - /** - * Returns a Boolean value that indicates whether the current command is supported on the current range. - * @param commandId Specifies a command identifier. + /** + * Returns a Boolean value that indicates whether the current command is supported on the current range. + * @param commandId Specifies a command identifier. */ queryCommandSupported(commandId: string): boolean; - /** - * Returns the current value of the document, range, or current selection for the given command. - * @param commandId String that specifies a command identifier. + /** + * Returns the current value of the document, range, or current selection for the given command. + * @param commandId String that specifies a command identifier. */ queryCommandValue(commandId: string): string; /** @deprecated */ releaseEvents(): void; - /** - * Writes one or more HTML expressions to a document in the specified window. - * @param content Specifies the text and HTML tags to write. + /** + * Writes one or more HTML expressions to a document in the specified window. + * @param content Specifies the text and HTML tags to write. */ write(...text: string[]): void; - /** - * Writes one or more HTML expressions, followed by a carriage return, to a document in the specified window. - * @param content The text and HTML tags to write. + /** + * Writes one or more HTML expressions, followed by a carriage return, to a document in the specified window. + * @param content The text and HTML tags to write. */ writeln(...text: string[]): void; addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -4709,11 +4850,13 @@ interface DocumentEvent { createEvent(eventInterface: "ErrorEvent"): ErrorEvent; createEvent(eventInterface: "Event"): Event; createEvent(eventInterface: "Events"): Event; + createEvent(eventInterface: "FileReaderProgressEvent"): FileReaderProgressEvent; createEvent(eventInterface: "FocusEvent"): FocusEvent; createEvent(eventInterface: "FocusNavigationEvent"): FocusNavigationEvent; createEvent(eventInterface: "GamepadEvent"): GamepadEvent; createEvent(eventInterface: "HashChangeEvent"): HashChangeEvent; createEvent(eventInterface: "IDBVersionChangeEvent"): IDBVersionChangeEvent; + createEvent(eventInterface: "InputEvent"): InputEvent; createEvent(eventInterface: "KeyboardEvent"): KeyboardEvent; createEvent(eventInterface: "ListeningStateChangedEvent"): ListeningStateChangedEvent; createEvent(eventInterface: "MSGestureEvent"): MSGestureEvent; @@ -4786,10 +4929,13 @@ declare var DocumentFragment: { interface DocumentOrShadowRoot { readonly activeElement: Element | null; + /** + * Returns document's fullscreen element. + */ readonly fullscreenElement: Element | null; readonly pointerLockElement: Element | null; - /** - * Retrieves a collection of styleSheet objects representing the style sheets that correspond to each instance of a link or style object in the document. + /** + * Retrieves a collection of styleSheet objects representing the style sheets that correspond to each instance of a link or style object in the document. */ readonly styleSheets: StyleSheetList; caretPositionFromPoint(x: number, y: number): CaretPosition | null; @@ -4883,13 +5029,11 @@ interface Element extends Node, ParentNode, NonDocumentTypeChildNode, ChildNode, readonly assignedSlot: HTMLSlotElement | null; readonly attributes: NamedNodeMap; /** - * Allows for manipulation of element's class content attribute as a - * set of whitespace-separated tokens through a DOMTokenList object. + * Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. */ readonly classList: DOMTokenList; /** - * Returns the value of element's class content attribute. Can be set - * to change it. + * Returns the value of element's class content attribute. Can be set to change it. */ className: string; readonly clientHeight: number; @@ -4897,8 +5041,7 @@ interface Element extends Node, ParentNode, NonDocumentTypeChildNode, ChildNode, readonly clientTop: number; readonly clientWidth: number; /** - * Returns the value of element's id content attribute. Can be set to - * change it. + * Returns the value of element's id content attribute. Can be set to change it. */ id: string; /** @@ -4925,8 +5068,7 @@ interface Element extends Node, ParentNode, NonDocumentTypeChildNode, ChildNode, */ readonly shadowRoot: ShadowRoot | null; /** - * Returns the value of element's slot content attribute. Can be set to - * change it. + * Returns the value of element's slot content attribute. Can be set to change it. */ slot: string; /** @@ -4942,25 +5084,26 @@ interface Element extends Node, ParentNode, NonDocumentTypeChildNode, ChildNode, */ closest(selector: K): HTMLElementTagNameMap[K] | null; closest(selector: K): SVGElementTagNameMap[K] | null; - closest(selector: string): Element | null; + closest(selector: string): E | null; /** * Returns element's first attribute whose qualified name is qualifiedName, and null if there is no such attribute otherwise. */ getAttribute(qualifiedName: string): string | null; /** - * Returns element's attribute whose namespace is namespace and local name is localName, and null if there is - * no such attribute otherwise. + * Returns element's attribute whose namespace is namespace and local name is localName, and null if there is no such attribute otherwise. */ getAttributeNS(namespace: string | null, localName: string): string | null; /** - * Returns the qualified names of all element's attributes. - * Can contain duplicates. + * Returns the qualified names of all element's attributes. Can contain duplicates. */ getAttributeNames(): string[]; getAttributeNode(name: string): Attr | null; getAttributeNodeNS(namespaceURI: string, localName: string): Attr | null; getBoundingClientRect(): ClientRect | DOMRect; getClientRects(): ClientRectList | DOMRectList; + /** + * Returns a HTMLCollection of the elements in the object on which the method was invoked (a document or an element) that have all the classes given by classNames. The classNames argument is interpreted as a space-separated list of classes. + */ getElementsByClassName(classNames: string): HTMLCollectionOf; getElementsByTagName(qualifiedName: K): HTMLCollectionOf; getElementsByTagName(qualifiedName: K): HTMLCollectionOf; @@ -5001,11 +5144,8 @@ interface Element extends Node, ParentNode, NonDocumentTypeChildNode, ChildNode, removeAttributeNode(attr: Attr): Attr; /** * Displays element fullscreen and resolves promise when done. - * When supplied, options's navigationUI member indicates whether showing - * navigation UI while in fullscreen is preferred or not. If set to "show", navigation - * simplicity is preferred over screen space, and if set to "hide", more screen space - * is preferred. User agents are always free to honor user preference over the application's. The - * default value "auto" indicates no application preference. + * + * When supplied, options's navigationUI member indicates whether showing navigation UI while in fullscreen is preferred or not. If set to "show", navigation simplicity is preferred over screen space, and if set to "hide", more screen space is preferred. User agents are always free to honor user preference over the application's. The default value "auto" indicates no application preference. */ requestFullscreen(options?: FullscreenOptions): Promise; requestPointerLock(): void; @@ -5028,8 +5168,8 @@ interface Element extends Node, ParentNode, NonDocumentTypeChildNode, ChildNode, setAttributeNodeNS(attr: Attr): Attr | null; setPointerCapture(pointerId: number): void; /** - * If force is not given, "toggles" qualifiedName, removing it if it is - * present and adding it if it is not present. If force is true, adds qualifiedName. If force is false, removes qualifiedName. + * If force is not given, "toggles" qualifiedName, removing it if it is present and adding it if it is not present. If force is true, adds qualifiedName. If force is false, removes qualifiedName. + * * Returns true if qualifiedName is now present, and false otherwise. */ toggleAttribute(qualifiedName: string, force?: boolean): boolean; @@ -5076,21 +5216,28 @@ interface Event { */ readonly bubbles: boolean; cancelBubble: boolean; + /** + * Returns true or false depending on how event was initialized. Its return value does not always carry meaning, but true can indicate that part of the operation during which event was dispatched, can be canceled by invoking the preventDefault() method. + */ readonly cancelable: boolean; /** * Returns true or false depending on how event was initialized. True if event invokes listeners past a ShadowRoot node that is the root of its target, and false otherwise. */ readonly composed: boolean; /** - * Returns the object whose event listener's callback is currently being - * invoked. + * Returns the object whose event listener's callback is currently being invoked. */ readonly currentTarget: EventTarget | null; + /** + * Returns true if preventDefault() was invoked successfully to indicate cancelation, and false otherwise. + */ readonly defaultPrevented: boolean; + /** + * Returns the event's phase, which is one of NONE, CAPTURING_PHASE, AT_TARGET, and BUBBLING_PHASE. + */ readonly eventPhase: number; /** - * Returns true if event was dispatched by the user agent, and - * false otherwise. + * Returns true if event was dispatched by the user agent, and false otherwise. */ readonly isTrusted: boolean; returnValue: boolean; @@ -5101,23 +5248,24 @@ interface Event { */ readonly target: EventTarget | null; /** - * Returns the event's timestamp as the number of milliseconds measured relative to - * the time origin. + * Returns the event's timestamp as the number of milliseconds measured relative to the time origin. */ readonly timeStamp: number; /** - * Returns the type of event, e.g. - * "click", "hashchange", or - * "submit". + * Returns the type of event, e.g. "click", "hashchange", or "submit". */ readonly type: string; + /** + * Returns the item objects of event's path (objects on which listeners will be invoked), except for any nodes in shadow trees of which the shadow root's mode is "closed" that are not reachable from event's currentTarget. + */ composedPath(): EventTarget[]; initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void; + /** + * If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. + */ preventDefault(): void; /** - * Invoking this method prevents event from reaching - * any registered event listeners after the current one finishes running and, when dispatched in a tree, also prevents event from reaching any - * other objects. + * Invoking this method prevents event from reaching any registered event listeners after the current one finishes running and, when dispatched in a tree, also prevents event from reaching any other objects. */ stopImmediatePropagation(): void; /** @@ -5154,8 +5302,7 @@ interface EventSource extends EventTarget { onmessage: ((this: EventSource, ev: MessageEvent) => any) | null; onopen: ((this: EventSource, ev: Event) => any) | null; /** - * Returns the state of this EventSource object's connection. It can have the - * values described below. + * Returns the state of this EventSource object's connection. It can have the values described below. */ readonly readyState: number; /** @@ -5163,11 +5310,12 @@ interface EventSource extends EventTarget { */ readonly url: string; /** - * Returns true if the credentials mode - * for connection requests to the URL providing the - * event stream is set to "include", and false otherwise. + * Returns true if the credentials mode for connection requests to the URL providing the event stream is set to "include", and false otherwise. */ readonly withCredentials: boolean; + /** + * Aborts any instances of the fetch algorithm started for this EventSource object, and sets the readyState attribute to CLOSED. + */ close(): void; readonly CLOSED: number; readonly CONNECTING: number; @@ -5190,18 +5338,20 @@ declare var EventSource: { interface EventTarget { /** * Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. - * The options argument sets listener-specific options. For compatibility this can be a - * boolean, in which case the method behaves exactly as if the value was specified as options's capture. + * + * The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. + * * When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. + * * When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in §2.8 Observing event listeners. - * When set to true, options's once indicates that the callback will only be invoked once after which the event listener will - * be removed. + * + * When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. + * * The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. */ addEventListener(type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): void; /** - * Dispatches a synthetic event event to target and returns true - * if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. + * Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */ dispatchEvent(event: Event): boolean; /** @@ -5239,6 +5389,11 @@ interface External { IsSearchProviderInstalled(): void; } +declare var External: { + prototype: External; + new(): External; +}; + /** Provides information about files and allows JavaScript in a web page to access their content. */ interface File extends Blob { readonly lastModified: number; @@ -5263,23 +5418,23 @@ declare var FileList: { }; interface FileReaderEventMap { - "abort": ProgressEvent; - "error": ProgressEvent; - "load": ProgressEvent; - "loadend": ProgressEvent; - "loadstart": ProgressEvent; - "progress": ProgressEvent; + "abort": FileReaderProgressEvent; + "error": FileReaderProgressEvent; + "load": FileReaderProgressEvent; + "loadend": FileReaderProgressEvent; + "loadstart": FileReaderProgressEvent; + "progress": FileReaderProgressEvent; } /** Lets web applications asynchronously read the contents of files (or raw data buffers) stored on the user's computer, using File or Blob objects to specify the file or data to read. */ interface FileReader extends EventTarget { readonly error: DOMException | null; - onabort: ((this: FileReader, ev: ProgressEvent) => any) | null; - onerror: ((this: FileReader, ev: ProgressEvent) => any) | null; - onload: ((this: FileReader, ev: ProgressEvent) => any) | null; - onloadend: ((this: FileReader, ev: ProgressEvent) => any) | null; - onloadstart: ((this: FileReader, ev: ProgressEvent) => any) | null; - onprogress: ((this: FileReader, ev: ProgressEvent) => any) | null; + onabort: ((this: FileReader, ev: FileReaderProgressEvent) => any) | null; + onerror: ((this: FileReader, ev: FileReaderProgressEvent) => any) | null; + onload: ((this: FileReader, ev: FileReaderProgressEvent) => any) | null; + onloadend: ((this: FileReader, ev: FileReaderProgressEvent) => any) | null; + onloadstart: ((this: FileReader, ev: FileReaderProgressEvent) => any) | null; + onprogress: ((this: FileReader, ev: FileReaderProgressEvent) => any) | null; readonly readyState: number; readonly result: string | ArrayBuffer | null; abort(): void; @@ -5304,15 +5459,18 @@ declare var FileReader: { readonly LOADING: number; }; +interface FileReaderProgressEvent extends ProgressEvent { + readonly target: FileReader | null; +} + /** Focus-related events like focus, blur, focusin, or focusout. */ interface FocusEvent extends UIEvent { - readonly relatedTarget: EventTarget; - initFocusEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, relatedTargetArg: EventTarget): void; + readonly relatedTarget: EventTarget | null; } declare var FocusEvent: { prototype: FocusEvent; - new(typeArg: string, eventInitDict?: FocusEventInit): FocusEvent; + new(type: string, eventInitDict?: FocusEventInit): FocusEvent; }; interface FocusNavigationEvent extends Event { @@ -5355,7 +5513,7 @@ declare var GainNode: { new(context: BaseAudioContext, options?: GainOptions): GainNode; }; -/** An interface of the Gamepad API defines an individual gamepad or other controller, allowing access to information such as button presses, axis positions, and id. */ +/** This Gamepad API interface defines an individual gamepad or other controller, allowing access to information such as button presses, axis positions, and id. */ interface Gamepad { readonly axes: ReadonlyArray; readonly buttons: ReadonlyArray; @@ -5386,7 +5544,7 @@ declare var GamepadButton: { new(): GamepadButton; }; -/** An interface of the Gamepad API contains references to gamepads connected to the system, which is what the gamepad events Window.gamepadconnected and Window.gamepaddisconnected are fired in response to. */ +/** This Gamepad API interface contains references to gamepads connected to the system, which is what the gamepad events Window.gamepadconnected and Window.gamepaddisconnected are fired in response to. */ interface GamepadEvent extends Event { readonly gamepad: Gamepad; } @@ -5396,7 +5554,7 @@ declare var GamepadEvent: { new(type: string, eventInitDict: GamepadEventInit): GamepadEvent; }; -/** An interface of the Gamepad API represents hardware in the controller designed to provide haptic feedback to the user (if available), most commonly vibration hardware. */ +/** This Gamepad API interface represents hardware in the controller designed to provide haptic feedback to the user (if available), most commonly vibration hardware. */ interface GamepadHapticActuator { readonly type: GamepadHapticActuatorType; pulse(value: number, duration: number): Promise; @@ -5407,7 +5565,7 @@ declare var GamepadHapticActuator: { new(): GamepadHapticActuator; }; -/** An interface of the Gamepad API represents the pose of a WebVR controller at a given timestamp (which includes orientation, position, velocity, and acceleration information.) */ +/** This Gamepad API interface represents the pose of a WebVR controller at a given timestamp (which includes orientation, position, velocity, and acceleration information.) */ interface GamepadPose { readonly angularAcceleration: Float32Array | null; readonly angularVelocity: Float32Array | null; @@ -5425,13 +5583,23 @@ declare var GamepadPose: { }; interface GenericTransformStream { + /** + * Returns a readable stream whose chunks are strings resulting from running encoding's decoder on the chunks written to writable. + */ readonly readable: ReadableStream; /** - * Returns a writable stream which accepts string chunks and runs them through UTF-8's encoder before making them available to readable. + * Returns a writable stream which accepts BufferSource chunks and runs them through encoding's decoder before making them available to readable. + * * Typically this will be used via the pipeThrough() method on a ReadableStream source. - * textReadable - * .pipeThrough(new TextEncoderStream()) - * .pipeTo(byteWritable); + * + * ``` + * var decoder = new TextDecoderStream(encoding); + * byteReadable + * .pipeThrough(decoder) + * .pipeTo(textWritable); + * ``` + * + * If the error mode is "fatal" and encoding's decoder returns error, both readable and writable will be errored with a TypeError. */ readonly writable: WritableStream; } @@ -5473,6 +5641,8 @@ interface GlobalEventHandlersEventMap { "ended": Event; "error": ErrorEvent; "focus": FocusEvent; + "focusin": FocusEvent; + "focusout": FocusEvent; "gotpointercapture": PointerEvent; "input": Event; "invalid": Event; @@ -5533,9 +5703,9 @@ interface GlobalEventHandlersEventMap { } interface GlobalEventHandlers { - /** - * Fires when the user aborts the download. - * @param ev The event. + /** + * Fires when the user aborts the download. + * @param ev The event. */ onabort: ((this: GlobalEventHandlers, ev: UIEvent) => any) | null; onanimationcancel: ((this: GlobalEventHandlers, ev: AnimationEvent) => any) | null; @@ -5543,177 +5713,177 @@ interface GlobalEventHandlers { onanimationiteration: ((this: GlobalEventHandlers, ev: AnimationEvent) => any) | null; onanimationstart: ((this: GlobalEventHandlers, ev: AnimationEvent) => any) | null; onauxclick: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null; - /** - * Fires when the object loses the input focus. - * @param ev The focus event. + /** + * Fires when the object loses the input focus. + * @param ev The focus event. */ onblur: ((this: GlobalEventHandlers, ev: FocusEvent) => any) | null; oncancel: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Occurs when playback is possible, but would require further buffering. - * @param ev The event. + /** + * Occurs when playback is possible, but would require further buffering. + * @param ev The event. */ oncanplay: ((this: GlobalEventHandlers, ev: Event) => any) | null; oncanplaythrough: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Fires when the contents of the object or selection have changed. - * @param ev The event. + /** + * Fires when the contents of the object or selection have changed. + * @param ev The event. */ onchange: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Fires when the user clicks the left mouse button on the object - * @param ev The mouse event. + /** + * Fires when the user clicks the left mouse button on the object + * @param ev The mouse event. */ onclick: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null; onclose: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Fires when the user clicks the right mouse button in the client area, opening the context menu. - * @param ev The mouse event. + /** + * Fires when the user clicks the right mouse button in the client area, opening the context menu. + * @param ev The mouse event. */ oncontextmenu: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null; oncuechange: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Fires when the user double-clicks the object. - * @param ev The mouse event. + /** + * Fires when the user double-clicks the object. + * @param ev The mouse event. */ ondblclick: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null; - /** - * Fires on the source object continuously during a drag operation. - * @param ev The event. + /** + * Fires on the source object continuously during a drag operation. + * @param ev The event. */ ondrag: ((this: GlobalEventHandlers, ev: DragEvent) => any) | null; - /** - * Fires on the source object when the user releases the mouse at the close of a drag operation. - * @param ev The event. + /** + * Fires on the source object when the user releases the mouse at the close of a drag operation. + * @param ev The event. */ ondragend: ((this: GlobalEventHandlers, ev: DragEvent) => any) | null; - /** - * Fires on the target element when the user drags the object to a valid drop target. - * @param ev The drag event. + /** + * Fires on the target element when the user drags the object to a valid drop target. + * @param ev The drag event. */ ondragenter: ((this: GlobalEventHandlers, ev: DragEvent) => any) | null; ondragexit: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Fires on the target object when the user moves the mouse out of a valid drop target during a drag operation. - * @param ev The drag event. + /** + * Fires on the target object when the user moves the mouse out of a valid drop target during a drag operation. + * @param ev The drag event. */ ondragleave: ((this: GlobalEventHandlers, ev: DragEvent) => any) | null; - /** - * Fires on the target element continuously while the user drags the object over a valid drop target. - * @param ev The event. + /** + * Fires on the target element continuously while the user drags the object over a valid drop target. + * @param ev The event. */ ondragover: ((this: GlobalEventHandlers, ev: DragEvent) => any) | null; - /** - * Fires on the source object when the user starts to drag a text selection or selected object. - * @param ev The event. + /** + * Fires on the source object when the user starts to drag a text selection or selected object. + * @param ev The event. */ ondragstart: ((this: GlobalEventHandlers, ev: DragEvent) => any) | null; ondrop: ((this: GlobalEventHandlers, ev: DragEvent) => any) | null; - /** - * Occurs when the duration attribute is updated. - * @param ev The event. + /** + * Occurs when the duration attribute is updated. + * @param ev The event. */ ondurationchange: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Occurs when the media element is reset to its initial state. - * @param ev The event. + /** + * Occurs when the media element is reset to its initial state. + * @param ev The event. */ onemptied: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Occurs when the end of playback is reached. - * @param ev The event + /** + * Occurs when the end of playback is reached. + * @param ev The event */ onended: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Fires when an error occurs during object loading. - * @param ev The event. + /** + * Fires when an error occurs during object loading. + * @param ev The event. */ onerror: OnErrorEventHandler; - /** - * Fires when the object receives focus. - * @param ev The event. + /** + * Fires when the object receives focus. + * @param ev The event. */ onfocus: ((this: GlobalEventHandlers, ev: FocusEvent) => any) | null; ongotpointercapture: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null; oninput: ((this: GlobalEventHandlers, ev: Event) => any) | null; oninvalid: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Fires when the user presses a key. - * @param ev The keyboard event + /** + * Fires when the user presses a key. + * @param ev The keyboard event */ onkeydown: ((this: GlobalEventHandlers, ev: KeyboardEvent) => any) | null; - /** - * Fires when the user presses an alphanumeric key. - * @param ev The event. + /** + * Fires when the user presses an alphanumeric key. + * @param ev The event. */ onkeypress: ((this: GlobalEventHandlers, ev: KeyboardEvent) => any) | null; - /** - * Fires when the user releases a key. - * @param ev The keyboard event + /** + * Fires when the user releases a key. + * @param ev The keyboard event */ onkeyup: ((this: GlobalEventHandlers, ev: KeyboardEvent) => any) | null; - /** - * Fires immediately after the browser loads the object. - * @param ev The event. + /** + * Fires immediately after the browser loads the object. + * @param ev The event. */ onload: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Occurs when media data is loaded at the current playback position. - * @param ev The event. + /** + * Occurs when media data is loaded at the current playback position. + * @param ev The event. */ onloadeddata: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Occurs when the duration and dimensions of the media have been determined. - * @param ev The event. + /** + * Occurs when the duration and dimensions of the media have been determined. + * @param ev The event. */ onloadedmetadata: ((this: GlobalEventHandlers, ev: Event) => any) | null; onloadend: ((this: GlobalEventHandlers, ev: ProgressEvent) => any) | null; - /** - * Occurs when Internet Explorer begins looking for media data. - * @param ev The event. + /** + * Occurs when Internet Explorer begins looking for media data. + * @param ev The event. */ onloadstart: ((this: GlobalEventHandlers, ev: Event) => any) | null; onlostpointercapture: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null; - /** - * Fires when the user clicks the object with either mouse button. - * @param ev The mouse event. + /** + * Fires when the user clicks the object with either mouse button. + * @param ev The mouse event. */ onmousedown: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null; onmouseenter: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null; onmouseleave: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null; - /** - * Fires when the user moves the mouse over the object. - * @param ev The mouse event. + /** + * Fires when the user moves the mouse over the object. + * @param ev The mouse event. */ onmousemove: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null; - /** - * Fires when the user moves the mouse pointer outside the boundaries of the object. - * @param ev The mouse event. + /** + * Fires when the user moves the mouse pointer outside the boundaries of the object. + * @param ev The mouse event. */ onmouseout: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null; - /** - * Fires when the user moves the mouse pointer into the object. - * @param ev The mouse event. + /** + * Fires when the user moves the mouse pointer into the object. + * @param ev The mouse event. */ onmouseover: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null; - /** - * Fires when the user releases a mouse button while the mouse is over the object. - * @param ev The mouse event. + /** + * Fires when the user releases a mouse button while the mouse is over the object. + * @param ev The mouse event. */ onmouseup: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null; - /** - * Occurs when playback is paused. - * @param ev The event. + /** + * Occurs when playback is paused. + * @param ev The event. */ onpause: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Occurs when the play method is requested. - * @param ev The event. + /** + * Occurs when the play method is requested. + * @param ev The event. */ onplay: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Occurs when the audio or video has started playing. - * @param ev The event. + /** + * Occurs when the audio or video has started playing. + * @param ev The event. */ onplaying: ((this: GlobalEventHandlers, ev: Event) => any) | null; onpointercancel: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null; @@ -5724,59 +5894,59 @@ interface GlobalEventHandlers { onpointerout: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null; onpointerover: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null; onpointerup: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null; - /** - * Occurs to indicate progress while downloading media data. - * @param ev The event. + /** + * Occurs to indicate progress while downloading media data. + * @param ev The event. */ onprogress: ((this: GlobalEventHandlers, ev: ProgressEvent) => any) | null; - /** - * Occurs when the playback rate is increased or decreased. - * @param ev The event. + /** + * Occurs when the playback rate is increased or decreased. + * @param ev The event. */ onratechange: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Fires when the user resets a form. - * @param ev The event. + /** + * Fires when the user resets a form. + * @param ev The event. */ onreset: ((this: GlobalEventHandlers, ev: Event) => any) | null; onresize: ((this: GlobalEventHandlers, ev: UIEvent) => any) | null; - /** - * Fires when the user repositions the scroll box in the scroll bar on the object. - * @param ev The event. + /** + * Fires when the user repositions the scroll box in the scroll bar on the object. + * @param ev The event. */ onscroll: ((this: GlobalEventHandlers, ev: Event) => any) | null; onsecuritypolicyviolation: ((this: GlobalEventHandlers, ev: SecurityPolicyViolationEvent) => any) | null; - /** - * Occurs when the seek operation ends. - * @param ev The event. + /** + * Occurs when the seek operation ends. + * @param ev The event. */ onseeked: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Occurs when the current playback position is moved. - * @param ev The event. + /** + * Occurs when the current playback position is moved. + * @param ev The event. */ onseeking: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Fires when the current selection changes. - * @param ev The event. + /** + * Fires when the current selection changes. + * @param ev The event. */ onselect: ((this: GlobalEventHandlers, ev: Event) => any) | null; onselectionchange: ((this: GlobalEventHandlers, ev: Event) => any) | null; onselectstart: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Occurs when the download has stopped. - * @param ev The event. + /** + * Occurs when the download has stopped. + * @param ev The event. */ onstalled: ((this: GlobalEventHandlers, ev: Event) => any) | null; onsubmit: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Occurs if the load operation has been intentionally halted. - * @param ev The event. + /** + * Occurs if the load operation has been intentionally halted. + * @param ev The event. */ onsuspend: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Occurs to indicate the current playback position. - * @param ev The event. + /** + * Occurs to indicate the current playback position. + * @param ev The event. */ ontimeupdate: ((this: GlobalEventHandlers, ev: Event) => any) | null; ontoggle: ((this: GlobalEventHandlers, ev: Event) => any) | null; @@ -5788,14 +5958,14 @@ interface GlobalEventHandlers { ontransitionend: ((this: GlobalEventHandlers, ev: TransitionEvent) => any) | null; ontransitionrun: ((this: GlobalEventHandlers, ev: TransitionEvent) => any) | null; ontransitionstart: ((this: GlobalEventHandlers, ev: TransitionEvent) => any) | null; - /** - * Occurs when the volume is changed, or playback is muted or unmuted. - * @param ev The event. + /** + * Occurs when the volume is changed, or playback is muted or unmuted. + * @param ev The event. */ onvolumechange: ((this: GlobalEventHandlers, ev: Event) => any) | null; - /** - * Occurs when playback stops because the next frame of a video resource is not available. - * @param ev The event. + /** + * Occurs when playback stops because the next frame of a video resource is not available. + * @param ev The event. */ onwaiting: ((this: GlobalEventHandlers, ev: Event) => any) | null; onwheel: ((this: GlobalEventHandlers, ev: WheelEvent) => any) | null; @@ -5805,21 +5975,21 @@ interface GlobalEventHandlers { removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; } -interface GlobalFetch { - fetch(input: RequestInfo, init?: RequestInit): Promise; -} - interface HTMLAllCollection { /** * Returns the number of elements in the collection. */ readonly length: number; /** - * element = collection(index) + * Returns the item with index index from the collection (determined by tree order). */ item(nameOrIndex?: string): HTMLCollection | Element | null; /** - * element = collection(name) + * Returns the item with ID or name name from the collection. + * + * If there are multiple matching items, then an HTMLCollection object containing all those elements is returned. + * + * Only button, form, iframe, input, map, meta, object, select, and textarea elements can have a name for the purpose of this method; their name is given by the value of their name attribute. */ namedItem(name: string): HTMLCollection | Element | null; [index: number]: Element; @@ -5832,49 +6002,49 @@ declare var HTMLAllCollection: { /** Hyperlink elements and provides special properties and methods (beyond those of the regular HTMLElement object interface that they inherit from) for manipulating the layout and presentation of such elements. */ interface HTMLAnchorElement extends HTMLElement, HTMLHyperlinkElementUtils { - /** - * Sets or retrieves the character set used to encode the object. + /** + * Sets or retrieves the character set used to encode the object. */ /** @deprecated */ charset: string; - /** - * Sets or retrieves the coordinates of the object. + /** + * Sets or retrieves the coordinates of the object. */ /** @deprecated */ coords: string; download: string; - /** - * Sets or retrieves the language code of the object. + /** + * Sets or retrieves the language code of the object. */ hreflang: string; - /** - * Sets or retrieves the shape of the object. + /** + * Sets or retrieves the shape of the object. */ /** @deprecated */ name: string; ping: string; referrerPolicy: string; - /** - * Sets or retrieves the relationship between the object and the destination of the link. + /** + * Sets or retrieves the relationship between the object and the destination of the link. */ rel: string; readonly relList: DOMTokenList; - /** - * Sets or retrieves the relationship between the object and the destination of the link. + /** + * Sets or retrieves the relationship between the object and the destination of the link. */ /** @deprecated */ rev: string; - /** - * Sets or retrieves the shape of the object. + /** + * Sets or retrieves the shape of the object. */ /** @deprecated */ shape: string; - /** - * Sets or retrieves the window or frame at which to target content. + /** + * Sets or retrieves the window or frame at which to target content. */ target: string; - /** - * Retrieves or sets the text of the object as a string. + /** + * Retrieves or sets the text of the object as a string. */ text: string; type: string; @@ -5892,33 +6062,33 @@ declare var HTMLAnchorElement: { interface HTMLAppletElement extends HTMLElement { /** @deprecated */ align: string; - /** - * Sets or retrieves a text alternative to the graphic. + /** + * Sets or retrieves a text alternative to the graphic. */ /** @deprecated */ alt: string; - /** - * Sets or retrieves a character string that can be used to implement your own archive functionality for the object. + /** + * Sets or retrieves a character string that can be used to implement your own archive functionality for the object. */ /** @deprecated */ archive: string; /** @deprecated */ code: string; - /** - * Sets or retrieves the URL of the component. + /** + * Sets or retrieves the URL of the component. */ /** @deprecated */ codeBase: string; readonly form: HTMLFormElement | null; - /** - * Sets or retrieves the height of the object. + /** + * Sets or retrieves the height of the object. */ /** @deprecated */ height: string; /** @deprecated */ hspace: number; - /** - * Sets or retrieves the shape of the object. + /** + * Sets or retrieves the shape of the object. */ /** @deprecated */ name: string; @@ -5941,17 +6111,17 @@ declare var HTMLAppletElement: { /** Provides special properties and methods (beyond those of the regular object HTMLElement interface it also has available to it by inheritance) for manipulating the layout and presentation of elements. */ interface HTMLAreaElement extends HTMLElement, HTMLHyperlinkElementUtils { - /** - * Sets or retrieves a text alternative to the graphic. + /** + * Sets or retrieves a text alternative to the graphic. */ alt: string; - /** - * Sets or retrieves the coordinates of the object. + /** + * Sets or retrieves the coordinates of the object. */ coords: string; download: string; - /** - * Sets or gets whether clicks in this region cause action. + /** + * Sets or gets whether clicks in this region cause action. */ /** @deprecated */ noHref: boolean; @@ -5959,12 +6129,12 @@ interface HTMLAreaElement extends HTMLElement, HTMLHyperlinkElementUtils { referrerPolicy: string; rel: string; readonly relList: DOMTokenList; - /** - * Sets or retrieves the shape of the object. + /** + * Sets or retrieves the shape of the object. */ shape: string; - /** - * Sets or retrieves the window or frame at which to target content. + /** + * Sets or retrieves the window or frame at which to target content. */ target: string; addEventListener(type: K, listener: (this: HTMLAreaElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -5993,8 +6163,8 @@ declare var HTMLAudioElement: { /** A HTML line break element (
). It inherits from HTMLElement. */ interface HTMLBRElement extends HTMLElement { - /** - * Sets or retrieves the side on which floating objects are not to be positioned when any IHTMLBlockElement is inserted into the document. + /** + * Sets or retrieves the side on which floating objects are not to be positioned when any IHTMLBlockElement is inserted into the document. */ /** @deprecated */ clear: string; @@ -6011,12 +6181,12 @@ declare var HTMLBRElement: { /** Contains the base URI for a document. This object inherits all of the properties and methods as described in the HTMLElement interface. */ interface HTMLBaseElement extends HTMLElement { - /** - * Gets or sets the baseline URL on which relative links are based. + /** + * Gets or sets the baseline URL on which relative links are based. */ href: string; - /** - * Sets or retrieves the window or frame at which to target content. + /** + * Sets or retrieves the window or frame at which to target content. */ target: string; addEventListener(type: K, listener: (this: HTMLBaseElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; @@ -6032,13 +6202,13 @@ declare var HTMLBaseElement: { /** Provides special properties (beyond the regular HTMLElement interface it also has available to it by inheritance) for manipulating elements. */ interface HTMLBaseFontElement extends HTMLElement, DOML2DeprecatedColorProperty { - /** - * Sets or retrieves the current typeface family. + /** + * Sets or retrieves the current typeface family. */ /** @deprecated */ face: string; - /** - * Sets or retrieves the font size of the object. + /** + * Sets or retrieves the font size of the object. */ /** @deprecated */ size: number; @@ -6089,68 +6259,68 @@ declare var HTMLBodyElement: { /** Provides properties and methods (beyond the regular HTMLElement interface it also has available to it by inheritance) for manipulating