mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #8471 from Microsoft/controlFlowCaching
Improved control flow caching
This commit is contained in:
+71
-46
@@ -129,8 +129,8 @@ namespace ts {
|
||||
let Symbol: { new (flags: SymbolFlags, name: string): Symbol };
|
||||
let classifiableNames: Map<string>;
|
||||
|
||||
const unreachableFlow: FlowNode = { kind: FlowKind.Unreachable };
|
||||
const reportedUnreachableFlow: FlowNode = { kind: FlowKind.Unreachable };
|
||||
const unreachableFlow: FlowNode = { flags: FlowFlags.Unreachable };
|
||||
const reportedUnreachableFlow: FlowNode = { flags: FlowFlags.Unreachable };
|
||||
|
||||
function bindSourceFile(f: SourceFile, opts: CompilerOptions) {
|
||||
file = f;
|
||||
@@ -471,7 +471,7 @@ namespace ts {
|
||||
savedActiveLabels = activeLabels;
|
||||
|
||||
hasExplicitReturn = false;
|
||||
currentFlow = { kind: FlowKind.Start };
|
||||
currentFlow = { flags: FlowFlags.Start };
|
||||
currentBreakTarget = undefined;
|
||||
currentContinueTarget = undefined;
|
||||
activeLabels = undefined;
|
||||
@@ -483,7 +483,7 @@ namespace ts {
|
||||
|
||||
bindReachableStatement(node);
|
||||
|
||||
if (currentFlow.kind !== FlowKind.Unreachable && isFunctionLikeKind(kind) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
|
||||
if (!(currentFlow.flags & FlowFlags.Unreachable) && isFunctionLikeKind(kind) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
|
||||
flags |= NodeFlags.HasImplicitReturn;
|
||||
if (hasExplicitReturn) {
|
||||
flags |= NodeFlags.HasExplicitReturn;
|
||||
@@ -639,55 +639,80 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function createFlowLabel(): FlowLabel {
|
||||
function createBranchLabel(): FlowLabel {
|
||||
return {
|
||||
kind: FlowKind.Label,
|
||||
flags: FlowFlags.BranchLabel,
|
||||
antecedents: undefined
|
||||
};
|
||||
}
|
||||
|
||||
function createFlowLoopLabel(): FlowLabel {
|
||||
function createLoopLabel(): FlowLabel {
|
||||
return {
|
||||
kind: FlowKind.LoopLabel,
|
||||
flags: FlowFlags.LoopLabel,
|
||||
antecedents: undefined
|
||||
};
|
||||
}
|
||||
|
||||
function setFlowNodeReferenced(flow: FlowNode) {
|
||||
// On first reference we set the Referenced flag, thereafter we set the Shared flag
|
||||
flow.flags |= flow.flags & FlowFlags.Referenced ? FlowFlags.Shared : FlowFlags.Referenced;
|
||||
}
|
||||
|
||||
function addAntecedent(label: FlowLabel, antecedent: FlowNode): void {
|
||||
if (antecedent.kind !== FlowKind.Unreachable && !contains(label.antecedents, antecedent)) {
|
||||
if (!(antecedent.flags & FlowFlags.Unreachable) && !contains(label.antecedents, antecedent)) {
|
||||
(label.antecedents || (label.antecedents = [])).push(antecedent);
|
||||
setFlowNodeReferenced(antecedent);
|
||||
}
|
||||
}
|
||||
|
||||
function createFlowCondition(antecedent: FlowNode, expression: Expression, assumeTrue: boolean): FlowNode {
|
||||
if (antecedent.kind === FlowKind.Unreachable) {
|
||||
function createFlowCondition(flags: FlowFlags, antecedent: FlowNode, expression: Expression): FlowNode {
|
||||
if (antecedent.flags & FlowFlags.Unreachable) {
|
||||
return antecedent;
|
||||
}
|
||||
if (!expression) {
|
||||
return assumeTrue ? antecedent : unreachableFlow;
|
||||
return flags & FlowFlags.TrueCondition ? antecedent : unreachableFlow;
|
||||
}
|
||||
if (expression.kind === SyntaxKind.TrueKeyword && !assumeTrue || expression.kind === SyntaxKind.FalseKeyword && assumeTrue) {
|
||||
if (expression.kind === SyntaxKind.TrueKeyword && flags & FlowFlags.FalseCondition ||
|
||||
expression.kind === SyntaxKind.FalseKeyword && flags & FlowFlags.TrueCondition) {
|
||||
return unreachableFlow;
|
||||
}
|
||||
if (!isNarrowingExpression(expression)) {
|
||||
return antecedent;
|
||||
}
|
||||
setFlowNodeReferenced(antecedent);
|
||||
return <FlowCondition>{
|
||||
kind: FlowKind.Condition,
|
||||
flags,
|
||||
antecedent,
|
||||
expression,
|
||||
assumeTrue
|
||||
};
|
||||
}
|
||||
|
||||
function createFlowAssignment(antecedent: FlowNode, node: Expression | VariableDeclaration | BindingElement): FlowNode {
|
||||
setFlowNodeReferenced(antecedent);
|
||||
return <FlowAssignment>{
|
||||
kind: FlowKind.Assignment,
|
||||
flags: FlowFlags.Assignment,
|
||||
antecedent,
|
||||
node
|
||||
};
|
||||
}
|
||||
|
||||
function skipSimpleConditionalFlow(flow: FlowNode) {
|
||||
// We skip over simple conditional flows of the form 'x ? aaa : bbb', where 'aaa' and 'bbb' contain
|
||||
// no constructs that affect control flow type analysis. Such simple flows have no effect on the
|
||||
// code paths that follow and ignoring them means we'll do less work.
|
||||
if (flow.flags & FlowFlags.BranchLabel && (<FlowLabel>flow).antecedents.length === 2) {
|
||||
const a = (<FlowLabel>flow).antecedents[0];
|
||||
const b = (<FlowLabel>flow).antecedents[1];
|
||||
if ((a.flags & FlowFlags.TrueCondition && b.flags & FlowFlags.FalseCondition ||
|
||||
a.flags & FlowFlags.FalseCondition && b.flags & FlowFlags.TrueCondition) &&
|
||||
(<FlowCondition>a).antecedent === (<FlowCondition>b).antecedent &&
|
||||
(<FlowCondition>a).expression === (<FlowCondition>b).expression) {
|
||||
return (<FlowCondition>a).antecedent;
|
||||
}
|
||||
}
|
||||
return flow;
|
||||
}
|
||||
|
||||
function finishFlowLabel(flow: FlowLabel): FlowNode {
|
||||
const antecedents = flow.antecedents;
|
||||
if (!antecedents) {
|
||||
@@ -696,7 +721,7 @@ namespace ts {
|
||||
if (antecedents.length === 1) {
|
||||
return antecedents[0];
|
||||
}
|
||||
return flow;
|
||||
return skipSimpleConditionalFlow(flow);
|
||||
}
|
||||
|
||||
function isStatementCondition(node: Node) {
|
||||
@@ -747,8 +772,8 @@ namespace ts {
|
||||
currentTrueTarget = saveTrueTarget;
|
||||
currentFalseTarget = saveFalseTarget;
|
||||
if (!node || !isLogicalExpression(node)) {
|
||||
addAntecedent(trueTarget, createFlowCondition(currentFlow, node, /*assumeTrue*/ true));
|
||||
addAntecedent(falseTarget, createFlowCondition(currentFlow, node, /*assumeTrue*/ false));
|
||||
addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node));
|
||||
addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,9 +788,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindWhileStatement(node: WhileStatement): void {
|
||||
const preWhileLabel = createFlowLoopLabel();
|
||||
const preBodyLabel = createFlowLabel();
|
||||
const postWhileLabel = createFlowLabel();
|
||||
const preWhileLabel = createLoopLabel();
|
||||
const preBodyLabel = createBranchLabel();
|
||||
const postWhileLabel = createBranchLabel();
|
||||
addAntecedent(preWhileLabel, currentFlow);
|
||||
currentFlow = preWhileLabel;
|
||||
bindCondition(node.expression, preBodyLabel, postWhileLabel);
|
||||
@@ -776,9 +801,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindDoStatement(node: DoStatement): void {
|
||||
const preDoLabel = createFlowLoopLabel();
|
||||
const preConditionLabel = createFlowLabel();
|
||||
const postDoLabel = createFlowLabel();
|
||||
const preDoLabel = createLoopLabel();
|
||||
const preConditionLabel = createBranchLabel();
|
||||
const postDoLabel = createBranchLabel();
|
||||
addAntecedent(preDoLabel, currentFlow);
|
||||
currentFlow = preDoLabel;
|
||||
bindIterativeStatement(node.statement, postDoLabel, preConditionLabel);
|
||||
@@ -789,9 +814,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindForStatement(node: ForStatement): void {
|
||||
const preLoopLabel = createFlowLoopLabel();
|
||||
const preBodyLabel = createFlowLabel();
|
||||
const postLoopLabel = createFlowLabel();
|
||||
const preLoopLabel = createLoopLabel();
|
||||
const preBodyLabel = createBranchLabel();
|
||||
const postLoopLabel = createBranchLabel();
|
||||
bind(node.initializer);
|
||||
addAntecedent(preLoopLabel, currentFlow);
|
||||
currentFlow = preLoopLabel;
|
||||
@@ -804,8 +829,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindForInOrForOfStatement(node: ForInStatement | ForOfStatement): void {
|
||||
const preLoopLabel = createFlowLoopLabel();
|
||||
const postLoopLabel = createFlowLabel();
|
||||
const preLoopLabel = createLoopLabel();
|
||||
const postLoopLabel = createBranchLabel();
|
||||
addAntecedent(preLoopLabel, currentFlow);
|
||||
currentFlow = preLoopLabel;
|
||||
bind(node.expression);
|
||||
@@ -820,9 +845,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindIfStatement(node: IfStatement): void {
|
||||
const thenLabel = createFlowLabel();
|
||||
const elseLabel = createFlowLabel();
|
||||
const postIfLabel = createFlowLabel();
|
||||
const thenLabel = createBranchLabel();
|
||||
const elseLabel = createBranchLabel();
|
||||
const postIfLabel = createBranchLabel();
|
||||
bindCondition(node.expression, thenLabel, elseLabel);
|
||||
currentFlow = finishFlowLabel(thenLabel);
|
||||
bind(node.thenStatement);
|
||||
@@ -875,7 +900,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindTryStatement(node: TryStatement): void {
|
||||
const postFinallyLabel = createFlowLabel();
|
||||
const postFinallyLabel = createBranchLabel();
|
||||
const preTryFlow = currentFlow;
|
||||
// TODO: Every statement in try block is potentially an exit point!
|
||||
bind(node.tryBlock);
|
||||
@@ -893,7 +918,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindSwitchStatement(node: SwitchStatement): void {
|
||||
const postSwitchLabel = createFlowLabel();
|
||||
const postSwitchLabel = createBranchLabel();
|
||||
bind(node.expression);
|
||||
const saveBreakTarget = currentBreakTarget;
|
||||
const savePreSwitchCaseFlow = preSwitchCaseFlow;
|
||||
@@ -915,17 +940,17 @@ namespace ts {
|
||||
for (let i = 0; i < clauses.length; i++) {
|
||||
const clause = clauses[i];
|
||||
if (clause.statements.length) {
|
||||
if (currentFlow.kind === FlowKind.Unreachable) {
|
||||
if (currentFlow.flags & FlowFlags.Unreachable) {
|
||||
currentFlow = preSwitchCaseFlow;
|
||||
}
|
||||
else {
|
||||
const preCaseLabel = createFlowLabel();
|
||||
const preCaseLabel = createBranchLabel();
|
||||
addAntecedent(preCaseLabel, preSwitchCaseFlow);
|
||||
addAntecedent(preCaseLabel, currentFlow);
|
||||
currentFlow = finishFlowLabel(preCaseLabel);
|
||||
}
|
||||
bind(clause);
|
||||
if (currentFlow.kind !== FlowKind.Unreachable && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) {
|
||||
if (!(currentFlow.flags & FlowFlags.Unreachable) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) {
|
||||
errorOnFirstToken(clause, Diagnostics.Fallthrough_case_in_switch);
|
||||
}
|
||||
}
|
||||
@@ -951,8 +976,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindLabeledStatement(node: LabeledStatement): void {
|
||||
const preStatementLabel = createFlowLoopLabel();
|
||||
const postStatementLabel = createFlowLabel();
|
||||
const preStatementLabel = createLoopLabel();
|
||||
const postStatementLabel = createBranchLabel();
|
||||
bind(node.label);
|
||||
addAntecedent(preStatementLabel, currentFlow);
|
||||
const activeLabel = pushActiveLabel(node.label.text, postStatementLabel, preStatementLabel);
|
||||
@@ -1001,7 +1026,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindLogicalExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) {
|
||||
const preRightLabel = createFlowLabel();
|
||||
const preRightLabel = createBranchLabel();
|
||||
if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
|
||||
bindCondition(node.left, preRightLabel, falseTarget);
|
||||
}
|
||||
@@ -1031,7 +1056,7 @@ namespace ts {
|
||||
const operator = node.operatorToken.kind;
|
||||
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken) {
|
||||
if (isTopLevelLogicalExpression(node)) {
|
||||
const postExpressionLabel = createFlowLabel();
|
||||
const postExpressionLabel = createBranchLabel();
|
||||
bindLogicalExpression(node, postExpressionLabel, postExpressionLabel);
|
||||
currentFlow = finishFlowLabel(postExpressionLabel);
|
||||
}
|
||||
@@ -1048,9 +1073,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindConditionalExpressionFlow(node: ConditionalExpression) {
|
||||
const trueLabel = createFlowLabel();
|
||||
const falseLabel = createFlowLabel();
|
||||
const postExpressionLabel = createFlowLabel();
|
||||
const trueLabel = createBranchLabel();
|
||||
const falseLabel = createBranchLabel();
|
||||
const postExpressionLabel = createBranchLabel();
|
||||
bindCondition(node.condition, trueLabel, falseLabel);
|
||||
currentFlow = finishFlowLabel(trueLabel);
|
||||
bind(node.whenTrue);
|
||||
@@ -2065,7 +2090,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkUnreachable(node: Node): boolean {
|
||||
if (currentFlow.kind !== FlowKind.Unreachable) {
|
||||
if (!(currentFlow.flags & FlowFlags.Unreachable)) {
|
||||
return false;
|
||||
}
|
||||
if (currentFlow === unreachableFlow) {
|
||||
|
||||
+51
-25
@@ -183,6 +183,7 @@ namespace ts {
|
||||
|
||||
let flowStackStart = 0;
|
||||
let flowStackCount = 0;
|
||||
let visitedFlowCount = 0;
|
||||
|
||||
const tupleTypes: Map<TupleType> = {};
|
||||
const unionTypes: Map<UnionType> = {};
|
||||
@@ -199,6 +200,8 @@ namespace ts {
|
||||
const flowTypeCaches: Map<Type>[] = [];
|
||||
const flowStackNodes: FlowNode[] = [];
|
||||
const flowStackCacheKeys: string[] = [];
|
||||
const visitedFlowNodes: FlowNode[] = [];
|
||||
const visitedFlowTypes: Type[] = [];
|
||||
const potentialThisCollisions: Node[] = [];
|
||||
const awaitedTypeStack: number[] = [];
|
||||
|
||||
@@ -7581,34 +7584,57 @@ namespace ts {
|
||||
if (!reference.flowNode || declaredType === initialType && !(declaredType.flags & TypeFlags.Narrowable)) {
|
||||
return declaredType;
|
||||
}
|
||||
return getTypeAtFlowNode(reference.flowNode);
|
||||
const visitedFlowStart = visitedFlowCount;
|
||||
const result = getTypeAtFlowNode(reference.flowNode);
|
||||
visitedFlowCount = visitedFlowStart;
|
||||
return result;
|
||||
|
||||
function getTypeAtFlowNode(flow: FlowNode): Type {
|
||||
while (true) {
|
||||
switch (flow.kind) {
|
||||
case FlowKind.Assignment:
|
||||
const type = getTypeAtFlowAssignment(<FlowAssignment>flow);
|
||||
if (!type) {
|
||||
flow = (<FlowAssignment>flow).antecedent;
|
||||
continue;
|
||||
if (flow.flags & FlowFlags.Shared) {
|
||||
// We cache results of flow type resolution for shared nodes that were previously visited in
|
||||
// the same getFlowTypeOfReference invocation. A node is considered shared when it is the
|
||||
// antecedent of more than one node.
|
||||
for (let i = visitedFlowStart; i < visitedFlowCount; i++) {
|
||||
if (visitedFlowNodes[i] === flow) {
|
||||
return visitedFlowTypes[i];
|
||||
}
|
||||
return type;
|
||||
case FlowKind.Condition:
|
||||
return getTypeAtFlowCondition(<FlowCondition>flow);
|
||||
case FlowKind.Label:
|
||||
case FlowKind.LoopLabel:
|
||||
if ((<FlowLabel>flow).antecedents.length === 1) {
|
||||
flow = (<FlowLabel>flow).antecedents[0];
|
||||
continue;
|
||||
}
|
||||
return getTypeAtFlowLabel(<FlowLabel>flow);
|
||||
case FlowKind.Unreachable:
|
||||
// Unreachable code errors are reported in the binding phase. Here we
|
||||
// simply return the declared type to reduce follow-on errors.
|
||||
return declaredType;
|
||||
}
|
||||
}
|
||||
// At the top of the flow we have the initial type
|
||||
return initialType;
|
||||
let type: Type;
|
||||
if (flow.flags & FlowFlags.Assignment) {
|
||||
type = getTypeAtFlowAssignment(<FlowAssignment>flow);
|
||||
if (!type) {
|
||||
flow = (<FlowAssignment>flow).antecedent;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (flow.flags & FlowFlags.Condition) {
|
||||
type = getTypeAtFlowCondition(<FlowCondition>flow);
|
||||
}
|
||||
else if (flow.flags & FlowFlags.Label) {
|
||||
if ((<FlowLabel>flow).antecedents.length === 1) {
|
||||
flow = (<FlowLabel>flow).antecedents[0];
|
||||
continue;
|
||||
}
|
||||
type = getTypeAtFlowLabel(<FlowLabel>flow);
|
||||
}
|
||||
else if (flow.flags & FlowFlags.Unreachable) {
|
||||
// Unreachable code errors are reported in the binding phase. Here we
|
||||
// simply return the declared type to reduce follow-on errors.
|
||||
type = declaredType;
|
||||
}
|
||||
else {
|
||||
// At the top of the flow we have the initial type.
|
||||
type = initialType;
|
||||
}
|
||||
if (flow.flags & FlowFlags.Shared) {
|
||||
// Record visited node and the associated type in the cache.
|
||||
visitedFlowNodes[visitedFlowCount] = flow;
|
||||
visitedFlowTypes[visitedFlowCount] = type;
|
||||
visitedFlowCount++;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7644,7 +7670,7 @@ namespace ts {
|
||||
|
||||
function getTypeAtFlowCondition(flow: FlowCondition) {
|
||||
const type = getTypeAtFlowNode(flow.antecedent);
|
||||
return type && narrowType(type, flow.expression, flow.assumeTrue);
|
||||
return type && narrowType(type, flow.expression, (flow.flags & FlowFlags.TrueCondition) !== 0);
|
||||
}
|
||||
|
||||
function getTypeAtFlowNodeCached(flow: FlowNode) {
|
||||
@@ -7676,7 +7702,7 @@ namespace ts {
|
||||
function getTypeAtFlowLabel(flow: FlowLabel) {
|
||||
const antecedentTypes: Type[] = [];
|
||||
for (const antecedent of flow.antecedents) {
|
||||
const type = flow.kind === FlowKind.LoopLabel ?
|
||||
const type = flow.flags & FlowFlags.LoopLabel ?
|
||||
getTypeAtFlowNodeCached(antecedent) :
|
||||
getTypeAtFlowNode(antecedent);
|
||||
if (!type) {
|
||||
|
||||
+13
-9
@@ -1515,17 +1515,22 @@ namespace ts {
|
||||
isBracketed: boolean;
|
||||
}
|
||||
|
||||
export const enum FlowKind {
|
||||
Unreachable,
|
||||
Start,
|
||||
Label,
|
||||
LoopLabel,
|
||||
Assignment,
|
||||
Condition
|
||||
export const enum FlowFlags {
|
||||
Unreachable = 1 << 0, // Unreachable code
|
||||
Start = 1 << 1, // Start of flow graph
|
||||
BranchLabel = 1 << 2, // Non-looping junction
|
||||
LoopLabel = 1 << 3, // Looping junction
|
||||
Assignment = 1 << 4, // Assignment
|
||||
TrueCondition = 1 << 5, // Condition known to be true
|
||||
FalseCondition = 1 << 6, // Condition known to be false
|
||||
Referenced = 1 << 7, // Referenced as antecedent once
|
||||
Shared = 1 << 8, // Referenced as antecedent more than once
|
||||
Label = BranchLabel | LoopLabel,
|
||||
Condition = TrueCondition | FalseCondition
|
||||
}
|
||||
|
||||
export interface FlowNode {
|
||||
kind: FlowKind; // Node kind
|
||||
flags: FlowFlags;
|
||||
id?: number; // Node id used by flow type cache in checker
|
||||
}
|
||||
|
||||
@@ -1545,7 +1550,6 @@ namespace ts {
|
||||
// node's location in the control flow.
|
||||
export interface FlowCondition extends FlowNode {
|
||||
expression: Expression;
|
||||
assumeTrue: boolean;
|
||||
antecedent: FlowNode;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ if (isNodeList(sourceObj)) {
|
||||
if (isHTMLCollection(sourceObj)) {
|
||||
>isHTMLCollection(sourceObj) : boolean
|
||||
>isHTMLCollection : (sourceObj: any) => sourceObj is HTMLCollection
|
||||
>sourceObj : HTMLCollection | { a: string; }
|
||||
>sourceObj : { a: string; } | HTMLCollection
|
||||
|
||||
sourceObj.length;
|
||||
>sourceObj.length : number
|
||||
@@ -99,7 +99,7 @@ if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) {
|
||||
>isNodeList(sourceObj) || isHTMLCollection(sourceObj) : boolean
|
||||
>isNodeList(sourceObj) : boolean
|
||||
>isNodeList : (sourceObj: any) => sourceObj is NodeList
|
||||
>sourceObj : HTMLCollection | { a: string; }
|
||||
>sourceObj : { a: string; } | HTMLCollection
|
||||
>isHTMLCollection(sourceObj) : boolean
|
||||
>isHTMLCollection : (sourceObj: any) => sourceObj is HTMLCollection
|
||||
>sourceObj : { a: string; }
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
//// [controlFlowCaching.ts]
|
||||
|
||||
// Repro for #8401
|
||||
|
||||
function f(dim, offsets, arr, acommon, centerAnchorLimit, g, has, lin) {
|
||||
var isRtl = this._isRtl(); // chart mirroring
|
||||
// prepare variable
|
||||
var o = this.opt, ta = this.chart.theme.axis, position = o.position,
|
||||
leftBottom = position !== "rightOrTop", rotation = o.rotation % 360,
|
||||
start, stop, titlePos, titleRotation = 0, titleOffset, axisVector, tickVector, anchorOffset, labelOffset, labelAlign,
|
||||
labelGap = this.chart.theme.axis.tick.labelGap,
|
||||
taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font),
|
||||
taTitleFont = o.titleFont || (ta.title && ta.title.font),
|
||||
taFontColor = o.fontColor || (ta.majorTick && ta.majorTick.fontColor) || (ta.tick && ta.tick.fontColor) || "black",
|
||||
taTitleFontColor = o.titleFontColor || (ta.title && ta.title.fontColor) || "black",
|
||||
taTitleGap = (o.titleGap == 0) ? 0 : o.titleGap || (ta.title && ta.title.gap) || 15,
|
||||
taTitleOrientation = o.titleOrientation || (ta.title && ta.title.orientation) || "axis",
|
||||
taMajorTick = this.chart.theme.getTick("major", o),
|
||||
taMinorTick = this.chart.theme.getTick("minor", o),
|
||||
taMicroTick = this.chart.theme.getTick("micro", o),
|
||||
|
||||
taStroke = "stroke" in o ? o.stroke : ta.stroke,
|
||||
size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
|
||||
cosr = Math.abs(Math.cos(rotation * Math.PI / 180)),
|
||||
sinr = Math.abs(Math.sin(rotation * Math.PI / 180)),
|
||||
tsize = taTitleFont ? g.normalizedLength(g.splitFontString(taTitleFont).size) : 0;
|
||||
if (rotation < 0) {
|
||||
rotation += 360;
|
||||
}
|
||||
var cachedLabelW = this._getMaxLabelSize();
|
||||
cachedLabelW = cachedLabelW && cachedLabelW.majLabelW;
|
||||
titleOffset = size * cosr + (cachedLabelW || 0) * sinr + labelGap + Math.max(taMajorTick.length > 0 ? taMajorTick.length : 0,
|
||||
taMinorTick.length > 0 ? taMinorTick.length : 0) +
|
||||
tsize + taTitleGap;
|
||||
axisVector = { x: isRtl ? -1 : 1, y: 0 }; // chart mirroring
|
||||
switch (rotation) {
|
||||
default:
|
||||
if (rotation < (90 - centerAnchorLimit)) {
|
||||
labelOffset.y = leftBottom ? size : 0;
|
||||
} else if (rotation < (90 + centerAnchorLimit)) {
|
||||
labelOffset.x = -size * 0.4;
|
||||
} else if (rotation < 180) {
|
||||
labelOffset.y = leftBottom ? 0 : -size;
|
||||
} else if (rotation < (270 - centerAnchorLimit)) {
|
||||
labelOffset.y = leftBottom ? 0 : -size;
|
||||
} else if (rotation < (270 + centerAnchorLimit)) {
|
||||
labelOffset.y = leftBottom ? size * 0.4 : 0;
|
||||
} else {
|
||||
labelOffset.y = leftBottom ? size : 0;
|
||||
}
|
||||
}
|
||||
|
||||
titleRotation = (taTitleOrientation && taTitleOrientation == "away") ? 180 : 0;
|
||||
titlePos.y = offsets.t - titleOffset + (titleRotation ? 0 : tsize);
|
||||
switch (labelAlign) {
|
||||
case "start":
|
||||
labelAlign = "end";
|
||||
break;
|
||||
case "end":
|
||||
labelAlign = "start";
|
||||
break;
|
||||
case "middle":
|
||||
labelOffset.y -= size;
|
||||
break;
|
||||
}
|
||||
|
||||
let _ = rotation;
|
||||
}
|
||||
|
||||
|
||||
//// [controlFlowCaching.js]
|
||||
// Repro for #8401
|
||||
function f(dim, offsets, arr, acommon, centerAnchorLimit, g, has, lin) {
|
||||
var isRtl = this._isRtl(); // chart mirroring
|
||||
// prepare variable
|
||||
var o = this.opt, ta = this.chart.theme.axis, position = o.position, leftBottom = position !== "rightOrTop", rotation = o.rotation % 360, start, stop, titlePos, titleRotation = 0, titleOffset, axisVector, tickVector, anchorOffset, labelOffset, labelAlign, labelGap = this.chart.theme.axis.tick.labelGap, taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font), taTitleFont = o.titleFont || (ta.title && ta.title.font), taFontColor = o.fontColor || (ta.majorTick && ta.majorTick.fontColor) || (ta.tick && ta.tick.fontColor) || "black", taTitleFontColor = o.titleFontColor || (ta.title && ta.title.fontColor) || "black", taTitleGap = (o.titleGap == 0) ? 0 : o.titleGap || (ta.title && ta.title.gap) || 15, taTitleOrientation = o.titleOrientation || (ta.title && ta.title.orientation) || "axis", taMajorTick = this.chart.theme.getTick("major", o), taMinorTick = this.chart.theme.getTick("minor", o), taMicroTick = this.chart.theme.getTick("micro", o), taStroke = "stroke" in o ? o.stroke : ta.stroke, size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0, cosr = Math.abs(Math.cos(rotation * Math.PI / 180)), sinr = Math.abs(Math.sin(rotation * Math.PI / 180)), tsize = taTitleFont ? g.normalizedLength(g.splitFontString(taTitleFont).size) : 0;
|
||||
if (rotation < 0) {
|
||||
rotation += 360;
|
||||
}
|
||||
var cachedLabelW = this._getMaxLabelSize();
|
||||
cachedLabelW = cachedLabelW && cachedLabelW.majLabelW;
|
||||
titleOffset = size * cosr + (cachedLabelW || 0) * sinr + labelGap + Math.max(taMajorTick.length > 0 ? taMajorTick.length : 0, taMinorTick.length > 0 ? taMinorTick.length : 0) +
|
||||
tsize + taTitleGap;
|
||||
axisVector = { x: isRtl ? -1 : 1, y: 0 }; // chart mirroring
|
||||
switch (rotation) {
|
||||
default:
|
||||
if (rotation < (90 - centerAnchorLimit)) {
|
||||
labelOffset.y = leftBottom ? size : 0;
|
||||
}
|
||||
else if (rotation < (90 + centerAnchorLimit)) {
|
||||
labelOffset.x = -size * 0.4;
|
||||
}
|
||||
else if (rotation < 180) {
|
||||
labelOffset.y = leftBottom ? 0 : -size;
|
||||
}
|
||||
else if (rotation < (270 - centerAnchorLimit)) {
|
||||
labelOffset.y = leftBottom ? 0 : -size;
|
||||
}
|
||||
else if (rotation < (270 + centerAnchorLimit)) {
|
||||
labelOffset.y = leftBottom ? size * 0.4 : 0;
|
||||
}
|
||||
else {
|
||||
labelOffset.y = leftBottom ? size : 0;
|
||||
}
|
||||
}
|
||||
titleRotation = (taTitleOrientation && taTitleOrientation == "away") ? 180 : 0;
|
||||
titlePos.y = offsets.t - titleOffset + (titleRotation ? 0 : tsize);
|
||||
switch (labelAlign) {
|
||||
case "start":
|
||||
labelAlign = "end";
|
||||
break;
|
||||
case "end":
|
||||
labelAlign = "start";
|
||||
break;
|
||||
case "middle":
|
||||
labelOffset.y -= size;
|
||||
break;
|
||||
}
|
||||
var _ = rotation;
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
=== tests/cases/compiler/controlFlowCaching.ts ===
|
||||
|
||||
// Repro for #8401
|
||||
|
||||
function f(dim, offsets, arr, acommon, centerAnchorLimit, g, has, lin) {
|
||||
>f : Symbol(f, Decl(controlFlowCaching.ts, 0, 0))
|
||||
>dim : Symbol(dim, Decl(controlFlowCaching.ts, 3, 11))
|
||||
>offsets : Symbol(offsets, Decl(controlFlowCaching.ts, 3, 15))
|
||||
>arr : Symbol(arr, Decl(controlFlowCaching.ts, 3, 24))
|
||||
>acommon : Symbol(acommon, Decl(controlFlowCaching.ts, 3, 29))
|
||||
>centerAnchorLimit : Symbol(centerAnchorLimit, Decl(controlFlowCaching.ts, 3, 38))
|
||||
>g : Symbol(g, Decl(controlFlowCaching.ts, 3, 57))
|
||||
>has : Symbol(has, Decl(controlFlowCaching.ts, 3, 60))
|
||||
>lin : Symbol(lin, Decl(controlFlowCaching.ts, 3, 65))
|
||||
|
||||
var isRtl = this._isRtl(); // chart mirroring
|
||||
>isRtl : Symbol(isRtl, Decl(controlFlowCaching.ts, 4, 7))
|
||||
|
||||
// prepare variable
|
||||
var o = this.opt, ta = this.chart.theme.axis, position = o.position,
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
>position : Symbol(position, Decl(controlFlowCaching.ts, 6, 49))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
|
||||
leftBottom = position !== "rightOrTop", rotation = o.rotation % 360,
|
||||
>leftBottom : Symbol(leftBottom, Decl(controlFlowCaching.ts, 6, 72))
|
||||
>position : Symbol(position, Decl(controlFlowCaching.ts, 6, 49))
|
||||
>rotation : Symbol(rotation, Decl(controlFlowCaching.ts, 7, 47))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
|
||||
start, stop, titlePos, titleRotation = 0, titleOffset, axisVector, tickVector, anchorOffset, labelOffset, labelAlign,
|
||||
>start : Symbol(start, Decl(controlFlowCaching.ts, 7, 76))
|
||||
>stop : Symbol(stop, Decl(controlFlowCaching.ts, 8, 14))
|
||||
>titlePos : Symbol(titlePos, Decl(controlFlowCaching.ts, 8, 20))
|
||||
>titleRotation : Symbol(titleRotation, Decl(controlFlowCaching.ts, 8, 30))
|
||||
>titleOffset : Symbol(titleOffset, Decl(controlFlowCaching.ts, 8, 49))
|
||||
>axisVector : Symbol(axisVector, Decl(controlFlowCaching.ts, 8, 62))
|
||||
>tickVector : Symbol(tickVector, Decl(controlFlowCaching.ts, 8, 74))
|
||||
>anchorOffset : Symbol(anchorOffset, Decl(controlFlowCaching.ts, 8, 86))
|
||||
>labelOffset : Symbol(labelOffset, Decl(controlFlowCaching.ts, 8, 100))
|
||||
>labelAlign : Symbol(labelAlign, Decl(controlFlowCaching.ts, 8, 113))
|
||||
|
||||
labelGap = this.chart.theme.axis.tick.labelGap,
|
||||
>labelGap : Symbol(labelGap, Decl(controlFlowCaching.ts, 8, 125))
|
||||
|
||||
taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font),
|
||||
>taFont : Symbol(taFont, Decl(controlFlowCaching.ts, 9, 55))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
|
||||
taTitleFont = o.titleFont || (ta.title && ta.title.font),
|
||||
>taTitleFont : Symbol(taTitleFont, Decl(controlFlowCaching.ts, 10, 92))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
|
||||
taFontColor = o.fontColor || (ta.majorTick && ta.majorTick.fontColor) || (ta.tick && ta.tick.fontColor) || "black",
|
||||
>taFontColor : Symbol(taFontColor, Decl(controlFlowCaching.ts, 11, 65))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
|
||||
taTitleFontColor = o.titleFontColor || (ta.title && ta.title.fontColor) || "black",
|
||||
>taTitleFontColor : Symbol(taTitleFontColor, Decl(controlFlowCaching.ts, 12, 123))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
|
||||
taTitleGap = (o.titleGap == 0) ? 0 : o.titleGap || (ta.title && ta.title.gap) || 15,
|
||||
>taTitleGap : Symbol(taTitleGap, Decl(controlFlowCaching.ts, 13, 91))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
|
||||
taTitleOrientation = o.titleOrientation || (ta.title && ta.title.orientation) || "axis",
|
||||
>taTitleOrientation : Symbol(taTitleOrientation, Decl(controlFlowCaching.ts, 14, 92))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
|
||||
taMajorTick = this.chart.theme.getTick("major", o),
|
||||
>taMajorTick : Symbol(taMajorTick, Decl(controlFlowCaching.ts, 15, 96))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
|
||||
taMinorTick = this.chart.theme.getTick("minor", o),
|
||||
>taMinorTick : Symbol(taMinorTick, Decl(controlFlowCaching.ts, 16, 59))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
|
||||
taMicroTick = this.chart.theme.getTick("micro", o),
|
||||
>taMicroTick : Symbol(taMicroTick, Decl(controlFlowCaching.ts, 17, 59))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
|
||||
taStroke = "stroke" in o ? o.stroke : ta.stroke,
|
||||
>taStroke : Symbol(taStroke, Decl(controlFlowCaching.ts, 18, 59))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
>o : Symbol(o, Decl(controlFlowCaching.ts, 6, 7))
|
||||
>ta : Symbol(ta, Decl(controlFlowCaching.ts, 6, 21))
|
||||
|
||||
size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
|
||||
>size : Symbol(size, Decl(controlFlowCaching.ts, 20, 56))
|
||||
>taFont : Symbol(taFont, Decl(controlFlowCaching.ts, 9, 55))
|
||||
>g : Symbol(g, Decl(controlFlowCaching.ts, 3, 57))
|
||||
>g : Symbol(g, Decl(controlFlowCaching.ts, 3, 57))
|
||||
>taFont : Symbol(taFont, Decl(controlFlowCaching.ts, 9, 55))
|
||||
|
||||
cosr = Math.abs(Math.cos(rotation * Math.PI / 180)),
|
||||
>cosr : Symbol(cosr, Decl(controlFlowCaching.ts, 21, 79))
|
||||
>Math.abs : Symbol(Math.abs, Decl(lib.d.ts, --, --))
|
||||
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>abs : Symbol(Math.abs, Decl(lib.d.ts, --, --))
|
||||
>Math.cos : Symbol(Math.cos, Decl(lib.d.ts, --, --))
|
||||
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>cos : Symbol(Math.cos, Decl(lib.d.ts, --, --))
|
||||
>rotation : Symbol(rotation, Decl(controlFlowCaching.ts, 7, 47))
|
||||
>Math.PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
|
||||
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
|
||||
|
||||
sinr = Math.abs(Math.sin(rotation * Math.PI / 180)),
|
||||
>sinr : Symbol(sinr, Decl(controlFlowCaching.ts, 22, 60))
|
||||
>Math.abs : Symbol(Math.abs, Decl(lib.d.ts, --, --))
|
||||
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>abs : Symbol(Math.abs, Decl(lib.d.ts, --, --))
|
||||
>Math.sin : Symbol(Math.sin, Decl(lib.d.ts, --, --))
|
||||
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>sin : Symbol(Math.sin, Decl(lib.d.ts, --, --))
|
||||
>rotation : Symbol(rotation, Decl(controlFlowCaching.ts, 7, 47))
|
||||
>Math.PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
|
||||
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
|
||||
|
||||
tsize = taTitleFont ? g.normalizedLength(g.splitFontString(taTitleFont).size) : 0;
|
||||
>tsize : Symbol(tsize, Decl(controlFlowCaching.ts, 23, 60))
|
||||
>taTitleFont : Symbol(taTitleFont, Decl(controlFlowCaching.ts, 10, 92))
|
||||
>g : Symbol(g, Decl(controlFlowCaching.ts, 3, 57))
|
||||
>g : Symbol(g, Decl(controlFlowCaching.ts, 3, 57))
|
||||
>taTitleFont : Symbol(taTitleFont, Decl(controlFlowCaching.ts, 10, 92))
|
||||
|
||||
if (rotation < 0) {
|
||||
>rotation : Symbol(rotation, Decl(controlFlowCaching.ts, 7, 47))
|
||||
|
||||
rotation += 360;
|
||||
>rotation : Symbol(rotation, Decl(controlFlowCaching.ts, 7, 47))
|
||||
}
|
||||
var cachedLabelW = this._getMaxLabelSize();
|
||||
>cachedLabelW : Symbol(cachedLabelW, Decl(controlFlowCaching.ts, 28, 7))
|
||||
|
||||
cachedLabelW = cachedLabelW && cachedLabelW.majLabelW;
|
||||
>cachedLabelW : Symbol(cachedLabelW, Decl(controlFlowCaching.ts, 28, 7))
|
||||
>cachedLabelW : Symbol(cachedLabelW, Decl(controlFlowCaching.ts, 28, 7))
|
||||
>cachedLabelW : Symbol(cachedLabelW, Decl(controlFlowCaching.ts, 28, 7))
|
||||
|
||||
titleOffset = size * cosr + (cachedLabelW || 0) * sinr + labelGap + Math.max(taMajorTick.length > 0 ? taMajorTick.length : 0,
|
||||
>titleOffset : Symbol(titleOffset, Decl(controlFlowCaching.ts, 8, 49))
|
||||
>size : Symbol(size, Decl(controlFlowCaching.ts, 20, 56))
|
||||
>cosr : Symbol(cosr, Decl(controlFlowCaching.ts, 21, 79))
|
||||
>cachedLabelW : Symbol(cachedLabelW, Decl(controlFlowCaching.ts, 28, 7))
|
||||
>sinr : Symbol(sinr, Decl(controlFlowCaching.ts, 22, 60))
|
||||
>labelGap : Symbol(labelGap, Decl(controlFlowCaching.ts, 8, 125))
|
||||
>Math.max : Symbol(Math.max, Decl(lib.d.ts, --, --))
|
||||
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>max : Symbol(Math.max, Decl(lib.d.ts, --, --))
|
||||
>taMajorTick : Symbol(taMajorTick, Decl(controlFlowCaching.ts, 15, 96))
|
||||
>taMajorTick : Symbol(taMajorTick, Decl(controlFlowCaching.ts, 15, 96))
|
||||
|
||||
taMinorTick.length > 0 ? taMinorTick.length : 0) +
|
||||
>taMinorTick : Symbol(taMinorTick, Decl(controlFlowCaching.ts, 16, 59))
|
||||
>taMinorTick : Symbol(taMinorTick, Decl(controlFlowCaching.ts, 16, 59))
|
||||
|
||||
tsize + taTitleGap;
|
||||
>tsize : Symbol(tsize, Decl(controlFlowCaching.ts, 23, 60))
|
||||
>taTitleGap : Symbol(taTitleGap, Decl(controlFlowCaching.ts, 13, 91))
|
||||
|
||||
axisVector = { x: isRtl ? -1 : 1, y: 0 }; // chart mirroring
|
||||
>axisVector : Symbol(axisVector, Decl(controlFlowCaching.ts, 8, 62))
|
||||
>x : Symbol(x, Decl(controlFlowCaching.ts, 33, 18))
|
||||
>isRtl : Symbol(isRtl, Decl(controlFlowCaching.ts, 4, 7))
|
||||
>y : Symbol(y, Decl(controlFlowCaching.ts, 33, 37))
|
||||
|
||||
switch (rotation) {
|
||||
>rotation : Symbol(rotation, Decl(controlFlowCaching.ts, 7, 47))
|
||||
|
||||
default:
|
||||
if (rotation < (90 - centerAnchorLimit)) {
|
||||
>rotation : Symbol(rotation, Decl(controlFlowCaching.ts, 7, 47))
|
||||
>centerAnchorLimit : Symbol(centerAnchorLimit, Decl(controlFlowCaching.ts, 3, 38))
|
||||
|
||||
labelOffset.y = leftBottom ? size : 0;
|
||||
>labelOffset : Symbol(labelOffset, Decl(controlFlowCaching.ts, 8, 100))
|
||||
>leftBottom : Symbol(leftBottom, Decl(controlFlowCaching.ts, 6, 72))
|
||||
>size : Symbol(size, Decl(controlFlowCaching.ts, 20, 56))
|
||||
|
||||
} else if (rotation < (90 + centerAnchorLimit)) {
|
||||
>rotation : Symbol(rotation, Decl(controlFlowCaching.ts, 7, 47))
|
||||
>centerAnchorLimit : Symbol(centerAnchorLimit, Decl(controlFlowCaching.ts, 3, 38))
|
||||
|
||||
labelOffset.x = -size * 0.4;
|
||||
>labelOffset : Symbol(labelOffset, Decl(controlFlowCaching.ts, 8, 100))
|
||||
>size : Symbol(size, Decl(controlFlowCaching.ts, 20, 56))
|
||||
|
||||
} else if (rotation < 180) {
|
||||
>rotation : Symbol(rotation, Decl(controlFlowCaching.ts, 7, 47))
|
||||
|
||||
labelOffset.y = leftBottom ? 0 : -size;
|
||||
>labelOffset : Symbol(labelOffset, Decl(controlFlowCaching.ts, 8, 100))
|
||||
>leftBottom : Symbol(leftBottom, Decl(controlFlowCaching.ts, 6, 72))
|
||||
>size : Symbol(size, Decl(controlFlowCaching.ts, 20, 56))
|
||||
|
||||
} else if (rotation < (270 - centerAnchorLimit)) {
|
||||
>rotation : Symbol(rotation, Decl(controlFlowCaching.ts, 7, 47))
|
||||
>centerAnchorLimit : Symbol(centerAnchorLimit, Decl(controlFlowCaching.ts, 3, 38))
|
||||
|
||||
labelOffset.y = leftBottom ? 0 : -size;
|
||||
>labelOffset : Symbol(labelOffset, Decl(controlFlowCaching.ts, 8, 100))
|
||||
>leftBottom : Symbol(leftBottom, Decl(controlFlowCaching.ts, 6, 72))
|
||||
>size : Symbol(size, Decl(controlFlowCaching.ts, 20, 56))
|
||||
|
||||
} else if (rotation < (270 + centerAnchorLimit)) {
|
||||
>rotation : Symbol(rotation, Decl(controlFlowCaching.ts, 7, 47))
|
||||
>centerAnchorLimit : Symbol(centerAnchorLimit, Decl(controlFlowCaching.ts, 3, 38))
|
||||
|
||||
labelOffset.y = leftBottom ? size * 0.4 : 0;
|
||||
>labelOffset : Symbol(labelOffset, Decl(controlFlowCaching.ts, 8, 100))
|
||||
>leftBottom : Symbol(leftBottom, Decl(controlFlowCaching.ts, 6, 72))
|
||||
>size : Symbol(size, Decl(controlFlowCaching.ts, 20, 56))
|
||||
|
||||
} else {
|
||||
labelOffset.y = leftBottom ? size : 0;
|
||||
>labelOffset : Symbol(labelOffset, Decl(controlFlowCaching.ts, 8, 100))
|
||||
>leftBottom : Symbol(leftBottom, Decl(controlFlowCaching.ts, 6, 72))
|
||||
>size : Symbol(size, Decl(controlFlowCaching.ts, 20, 56))
|
||||
}
|
||||
}
|
||||
|
||||
titleRotation = (taTitleOrientation && taTitleOrientation == "away") ? 180 : 0;
|
||||
>titleRotation : Symbol(titleRotation, Decl(controlFlowCaching.ts, 8, 30))
|
||||
>taTitleOrientation : Symbol(taTitleOrientation, Decl(controlFlowCaching.ts, 14, 92))
|
||||
>taTitleOrientation : Symbol(taTitleOrientation, Decl(controlFlowCaching.ts, 14, 92))
|
||||
|
||||
titlePos.y = offsets.t - titleOffset + (titleRotation ? 0 : tsize);
|
||||
>titlePos : Symbol(titlePos, Decl(controlFlowCaching.ts, 8, 20))
|
||||
>offsets : Symbol(offsets, Decl(controlFlowCaching.ts, 3, 15))
|
||||
>titleOffset : Symbol(titleOffset, Decl(controlFlowCaching.ts, 8, 49))
|
||||
>titleRotation : Symbol(titleRotation, Decl(controlFlowCaching.ts, 8, 30))
|
||||
>tsize : Symbol(tsize, Decl(controlFlowCaching.ts, 23, 60))
|
||||
|
||||
switch (labelAlign) {
|
||||
>labelAlign : Symbol(labelAlign, Decl(controlFlowCaching.ts, 8, 113))
|
||||
|
||||
case "start":
|
||||
labelAlign = "end";
|
||||
>labelAlign : Symbol(labelAlign, Decl(controlFlowCaching.ts, 8, 113))
|
||||
|
||||
break;
|
||||
case "end":
|
||||
labelAlign = "start";
|
||||
>labelAlign : Symbol(labelAlign, Decl(controlFlowCaching.ts, 8, 113))
|
||||
|
||||
break;
|
||||
case "middle":
|
||||
labelOffset.y -= size;
|
||||
>labelOffset : Symbol(labelOffset, Decl(controlFlowCaching.ts, 8, 100))
|
||||
>size : Symbol(size, Decl(controlFlowCaching.ts, 20, 56))
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
let _ = rotation;
|
||||
>_ : Symbol(_, Decl(controlFlowCaching.ts, 65, 7))
|
||||
>rotation : Symbol(rotation, Decl(controlFlowCaching.ts, 7, 47))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,607 @@
|
||||
=== tests/cases/compiler/controlFlowCaching.ts ===
|
||||
|
||||
// Repro for #8401
|
||||
|
||||
function f(dim, offsets, arr, acommon, centerAnchorLimit, g, has, lin) {
|
||||
>f : (dim: any, offsets: any, arr: any, acommon: any, centerAnchorLimit: any, g: any, has: any, lin: any) => void
|
||||
>dim : any
|
||||
>offsets : any
|
||||
>arr : any
|
||||
>acommon : any
|
||||
>centerAnchorLimit : any
|
||||
>g : any
|
||||
>has : any
|
||||
>lin : any
|
||||
|
||||
var isRtl = this._isRtl(); // chart mirroring
|
||||
>isRtl : any
|
||||
>this._isRtl() : any
|
||||
>this._isRtl : any
|
||||
>this : any
|
||||
>_isRtl : any
|
||||
|
||||
// prepare variable
|
||||
var o = this.opt, ta = this.chart.theme.axis, position = o.position,
|
||||
>o : any
|
||||
>this.opt : any
|
||||
>this : any
|
||||
>opt : any
|
||||
>ta : any
|
||||
>this.chart.theme.axis : any
|
||||
>this.chart.theme : any
|
||||
>this.chart : any
|
||||
>this : any
|
||||
>chart : any
|
||||
>theme : any
|
||||
>axis : any
|
||||
>position : any
|
||||
>o.position : any
|
||||
>o : any
|
||||
>position : any
|
||||
|
||||
leftBottom = position !== "rightOrTop", rotation = o.rotation % 360,
|
||||
>leftBottom : boolean
|
||||
>position !== "rightOrTop" : boolean
|
||||
>position : any
|
||||
>"rightOrTop" : string
|
||||
>rotation : number
|
||||
>o.rotation % 360 : number
|
||||
>o.rotation : any
|
||||
>o : any
|
||||
>rotation : any
|
||||
>360 : number
|
||||
|
||||
start, stop, titlePos, titleRotation = 0, titleOffset, axisVector, tickVector, anchorOffset, labelOffset, labelAlign,
|
||||
>start : any
|
||||
>stop : any
|
||||
>titlePos : any
|
||||
>titleRotation : number
|
||||
>0 : number
|
||||
>titleOffset : any
|
||||
>axisVector : any
|
||||
>tickVector : any
|
||||
>anchorOffset : any
|
||||
>labelOffset : any
|
||||
>labelAlign : any
|
||||
|
||||
labelGap = this.chart.theme.axis.tick.labelGap,
|
||||
>labelGap : any
|
||||
>this.chart.theme.axis.tick.labelGap : any
|
||||
>this.chart.theme.axis.tick : any
|
||||
>this.chart.theme.axis : any
|
||||
>this.chart.theme : any
|
||||
>this.chart : any
|
||||
>this : any
|
||||
>chart : any
|
||||
>theme : any
|
||||
>axis : any
|
||||
>tick : any
|
||||
>labelGap : any
|
||||
|
||||
taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font),
|
||||
>taFont : any
|
||||
>o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font) : any
|
||||
>o.font || (ta.majorTick && ta.majorTick.font) : any
|
||||
>o.font : any
|
||||
>o : any
|
||||
>font : any
|
||||
>(ta.majorTick && ta.majorTick.font) : any
|
||||
>ta.majorTick && ta.majorTick.font : any
|
||||
>ta.majorTick : any
|
||||
>ta : any
|
||||
>majorTick : any
|
||||
>ta.majorTick.font : any
|
||||
>ta.majorTick : any
|
||||
>ta : any
|
||||
>majorTick : any
|
||||
>font : any
|
||||
>(ta.tick && ta.tick.font) : any
|
||||
>ta.tick && ta.tick.font : any
|
||||
>ta.tick : any
|
||||
>ta : any
|
||||
>tick : any
|
||||
>ta.tick.font : any
|
||||
>ta.tick : any
|
||||
>ta : any
|
||||
>tick : any
|
||||
>font : any
|
||||
|
||||
taTitleFont = o.titleFont || (ta.title && ta.title.font),
|
||||
>taTitleFont : any
|
||||
>o.titleFont || (ta.title && ta.title.font) : any
|
||||
>o.titleFont : any
|
||||
>o : any
|
||||
>titleFont : any
|
||||
>(ta.title && ta.title.font) : any
|
||||
>ta.title && ta.title.font : any
|
||||
>ta.title : any
|
||||
>ta : any
|
||||
>title : any
|
||||
>ta.title.font : any
|
||||
>ta.title : any
|
||||
>ta : any
|
||||
>title : any
|
||||
>font : any
|
||||
|
||||
taFontColor = o.fontColor || (ta.majorTick && ta.majorTick.fontColor) || (ta.tick && ta.tick.fontColor) || "black",
|
||||
>taFontColor : any
|
||||
>o.fontColor || (ta.majorTick && ta.majorTick.fontColor) || (ta.tick && ta.tick.fontColor) || "black" : any
|
||||
>o.fontColor || (ta.majorTick && ta.majorTick.fontColor) || (ta.tick && ta.tick.fontColor) : any
|
||||
>o.fontColor || (ta.majorTick && ta.majorTick.fontColor) : any
|
||||
>o.fontColor : any
|
||||
>o : any
|
||||
>fontColor : any
|
||||
>(ta.majorTick && ta.majorTick.fontColor) : any
|
||||
>ta.majorTick && ta.majorTick.fontColor : any
|
||||
>ta.majorTick : any
|
||||
>ta : any
|
||||
>majorTick : any
|
||||
>ta.majorTick.fontColor : any
|
||||
>ta.majorTick : any
|
||||
>ta : any
|
||||
>majorTick : any
|
||||
>fontColor : any
|
||||
>(ta.tick && ta.tick.fontColor) : any
|
||||
>ta.tick && ta.tick.fontColor : any
|
||||
>ta.tick : any
|
||||
>ta : any
|
||||
>tick : any
|
||||
>ta.tick.fontColor : any
|
||||
>ta.tick : any
|
||||
>ta : any
|
||||
>tick : any
|
||||
>fontColor : any
|
||||
>"black" : string
|
||||
|
||||
taTitleFontColor = o.titleFontColor || (ta.title && ta.title.fontColor) || "black",
|
||||
>taTitleFontColor : any
|
||||
>o.titleFontColor || (ta.title && ta.title.fontColor) || "black" : any
|
||||
>o.titleFontColor || (ta.title && ta.title.fontColor) : any
|
||||
>o.titleFontColor : any
|
||||
>o : any
|
||||
>titleFontColor : any
|
||||
>(ta.title && ta.title.fontColor) : any
|
||||
>ta.title && ta.title.fontColor : any
|
||||
>ta.title : any
|
||||
>ta : any
|
||||
>title : any
|
||||
>ta.title.fontColor : any
|
||||
>ta.title : any
|
||||
>ta : any
|
||||
>title : any
|
||||
>fontColor : any
|
||||
>"black" : string
|
||||
|
||||
taTitleGap = (o.titleGap == 0) ? 0 : o.titleGap || (ta.title && ta.title.gap) || 15,
|
||||
>taTitleGap : any
|
||||
>(o.titleGap == 0) ? 0 : o.titleGap || (ta.title && ta.title.gap) || 15 : any
|
||||
>(o.titleGap == 0) : boolean
|
||||
>o.titleGap == 0 : boolean
|
||||
>o.titleGap : any
|
||||
>o : any
|
||||
>titleGap : any
|
||||
>0 : number
|
||||
>0 : number
|
||||
>o.titleGap || (ta.title && ta.title.gap) || 15 : any
|
||||
>o.titleGap || (ta.title && ta.title.gap) : any
|
||||
>o.titleGap : any
|
||||
>o : any
|
||||
>titleGap : any
|
||||
>(ta.title && ta.title.gap) : any
|
||||
>ta.title && ta.title.gap : any
|
||||
>ta.title : any
|
||||
>ta : any
|
||||
>title : any
|
||||
>ta.title.gap : any
|
||||
>ta.title : any
|
||||
>ta : any
|
||||
>title : any
|
||||
>gap : any
|
||||
>15 : number
|
||||
|
||||
taTitleOrientation = o.titleOrientation || (ta.title && ta.title.orientation) || "axis",
|
||||
>taTitleOrientation : any
|
||||
>o.titleOrientation || (ta.title && ta.title.orientation) || "axis" : any
|
||||
>o.titleOrientation || (ta.title && ta.title.orientation) : any
|
||||
>o.titleOrientation : any
|
||||
>o : any
|
||||
>titleOrientation : any
|
||||
>(ta.title && ta.title.orientation) : any
|
||||
>ta.title && ta.title.orientation : any
|
||||
>ta.title : any
|
||||
>ta : any
|
||||
>title : any
|
||||
>ta.title.orientation : any
|
||||
>ta.title : any
|
||||
>ta : any
|
||||
>title : any
|
||||
>orientation : any
|
||||
>"axis" : string
|
||||
|
||||
taMajorTick = this.chart.theme.getTick("major", o),
|
||||
>taMajorTick : any
|
||||
>this.chart.theme.getTick("major", o) : any
|
||||
>this.chart.theme.getTick : any
|
||||
>this.chart.theme : any
|
||||
>this.chart : any
|
||||
>this : any
|
||||
>chart : any
|
||||
>theme : any
|
||||
>getTick : any
|
||||
>"major" : string
|
||||
>o : any
|
||||
|
||||
taMinorTick = this.chart.theme.getTick("minor", o),
|
||||
>taMinorTick : any
|
||||
>this.chart.theme.getTick("minor", o) : any
|
||||
>this.chart.theme.getTick : any
|
||||
>this.chart.theme : any
|
||||
>this.chart : any
|
||||
>this : any
|
||||
>chart : any
|
||||
>theme : any
|
||||
>getTick : any
|
||||
>"minor" : string
|
||||
>o : any
|
||||
|
||||
taMicroTick = this.chart.theme.getTick("micro", o),
|
||||
>taMicroTick : any
|
||||
>this.chart.theme.getTick("micro", o) : any
|
||||
>this.chart.theme.getTick : any
|
||||
>this.chart.theme : any
|
||||
>this.chart : any
|
||||
>this : any
|
||||
>chart : any
|
||||
>theme : any
|
||||
>getTick : any
|
||||
>"micro" : string
|
||||
>o : any
|
||||
|
||||
taStroke = "stroke" in o ? o.stroke : ta.stroke,
|
||||
>taStroke : any
|
||||
>"stroke" in o ? o.stroke : ta.stroke : any
|
||||
>"stroke" in o : boolean
|
||||
>"stroke" : string
|
||||
>o : any
|
||||
>o.stroke : any
|
||||
>o : any
|
||||
>stroke : any
|
||||
>ta.stroke : any
|
||||
>ta : any
|
||||
>stroke : any
|
||||
|
||||
size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
|
||||
>size : any
|
||||
>taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0 : any
|
||||
>taFont : any
|
||||
>g.normalizedLength(g.splitFontString(taFont).size) : any
|
||||
>g.normalizedLength : any
|
||||
>g : any
|
||||
>normalizedLength : any
|
||||
>g.splitFontString(taFont).size : any
|
||||
>g.splitFontString(taFont) : any
|
||||
>g.splitFontString : any
|
||||
>g : any
|
||||
>splitFontString : any
|
||||
>taFont : any
|
||||
>size : any
|
||||
>0 : number
|
||||
|
||||
cosr = Math.abs(Math.cos(rotation * Math.PI / 180)),
|
||||
>cosr : number
|
||||
>Math.abs(Math.cos(rotation * Math.PI / 180)) : number
|
||||
>Math.abs : (x: number) => number
|
||||
>Math : Math
|
||||
>abs : (x: number) => number
|
||||
>Math.cos(rotation * Math.PI / 180) : number
|
||||
>Math.cos : (x: number) => number
|
||||
>Math : Math
|
||||
>cos : (x: number) => number
|
||||
>rotation * Math.PI / 180 : number
|
||||
>rotation * Math.PI : number
|
||||
>rotation : number
|
||||
>Math.PI : number
|
||||
>Math : Math
|
||||
>PI : number
|
||||
>180 : number
|
||||
|
||||
sinr = Math.abs(Math.sin(rotation * Math.PI / 180)),
|
||||
>sinr : number
|
||||
>Math.abs(Math.sin(rotation * Math.PI / 180)) : number
|
||||
>Math.abs : (x: number) => number
|
||||
>Math : Math
|
||||
>abs : (x: number) => number
|
||||
>Math.sin(rotation * Math.PI / 180) : number
|
||||
>Math.sin : (x: number) => number
|
||||
>Math : Math
|
||||
>sin : (x: number) => number
|
||||
>rotation * Math.PI / 180 : number
|
||||
>rotation * Math.PI : number
|
||||
>rotation : number
|
||||
>Math.PI : number
|
||||
>Math : Math
|
||||
>PI : number
|
||||
>180 : number
|
||||
|
||||
tsize = taTitleFont ? g.normalizedLength(g.splitFontString(taTitleFont).size) : 0;
|
||||
>tsize : any
|
||||
>taTitleFont ? g.normalizedLength(g.splitFontString(taTitleFont).size) : 0 : any
|
||||
>taTitleFont : any
|
||||
>g.normalizedLength(g.splitFontString(taTitleFont).size) : any
|
||||
>g.normalizedLength : any
|
||||
>g : any
|
||||
>normalizedLength : any
|
||||
>g.splitFontString(taTitleFont).size : any
|
||||
>g.splitFontString(taTitleFont) : any
|
||||
>g.splitFontString : any
|
||||
>g : any
|
||||
>splitFontString : any
|
||||
>taTitleFont : any
|
||||
>size : any
|
||||
>0 : number
|
||||
|
||||
if (rotation < 0) {
|
||||
>rotation < 0 : boolean
|
||||
>rotation : number
|
||||
>0 : number
|
||||
|
||||
rotation += 360;
|
||||
>rotation += 360 : number
|
||||
>rotation : number
|
||||
>360 : number
|
||||
}
|
||||
var cachedLabelW = this._getMaxLabelSize();
|
||||
>cachedLabelW : any
|
||||
>this._getMaxLabelSize() : any
|
||||
>this._getMaxLabelSize : any
|
||||
>this : any
|
||||
>_getMaxLabelSize : any
|
||||
|
||||
cachedLabelW = cachedLabelW && cachedLabelW.majLabelW;
|
||||
>cachedLabelW = cachedLabelW && cachedLabelW.majLabelW : any
|
||||
>cachedLabelW : any
|
||||
>cachedLabelW && cachedLabelW.majLabelW : any
|
||||
>cachedLabelW : any
|
||||
>cachedLabelW.majLabelW : any
|
||||
>cachedLabelW : any
|
||||
>majLabelW : any
|
||||
|
||||
titleOffset = size * cosr + (cachedLabelW || 0) * sinr + labelGap + Math.max(taMajorTick.length > 0 ? taMajorTick.length : 0,
|
||||
>titleOffset = size * cosr + (cachedLabelW || 0) * sinr + labelGap + Math.max(taMajorTick.length > 0 ? taMajorTick.length : 0, taMinorTick.length > 0 ? taMinorTick.length : 0) + tsize + taTitleGap : any
|
||||
>titleOffset : any
|
||||
>size * cosr + (cachedLabelW || 0) * sinr + labelGap + Math.max(taMajorTick.length > 0 ? taMajorTick.length : 0, taMinorTick.length > 0 ? taMinorTick.length : 0) + tsize + taTitleGap : any
|
||||
>size * cosr + (cachedLabelW || 0) * sinr + labelGap + Math.max(taMajorTick.length > 0 ? taMajorTick.length : 0, taMinorTick.length > 0 ? taMinorTick.length : 0) + tsize : any
|
||||
>size * cosr + (cachedLabelW || 0) * sinr + labelGap + Math.max(taMajorTick.length > 0 ? taMajorTick.length : 0, taMinorTick.length > 0 ? taMinorTick.length : 0) : any
|
||||
>size * cosr + (cachedLabelW || 0) * sinr + labelGap : any
|
||||
>size * cosr + (cachedLabelW || 0) * sinr : number
|
||||
>size * cosr : number
|
||||
>size : any
|
||||
>cosr : number
|
||||
>(cachedLabelW || 0) * sinr : number
|
||||
>(cachedLabelW || 0) : any
|
||||
>cachedLabelW || 0 : any
|
||||
>cachedLabelW : any
|
||||
>0 : number
|
||||
>sinr : number
|
||||
>labelGap : any
|
||||
>Math.max(taMajorTick.length > 0 ? taMajorTick.length : 0, taMinorTick.length > 0 ? taMinorTick.length : 0) : number
|
||||
>Math.max : (...values: number[]) => number
|
||||
>Math : Math
|
||||
>max : (...values: number[]) => number
|
||||
>taMajorTick.length > 0 ? taMajorTick.length : 0 : any
|
||||
>taMajorTick.length > 0 : boolean
|
||||
>taMajorTick.length : any
|
||||
>taMajorTick : any
|
||||
>length : any
|
||||
>0 : number
|
||||
>taMajorTick.length : any
|
||||
>taMajorTick : any
|
||||
>length : any
|
||||
>0 : number
|
||||
|
||||
taMinorTick.length > 0 ? taMinorTick.length : 0) +
|
||||
>taMinorTick.length > 0 ? taMinorTick.length : 0 : any
|
||||
>taMinorTick.length > 0 : boolean
|
||||
>taMinorTick.length : any
|
||||
>taMinorTick : any
|
||||
>length : any
|
||||
>0 : number
|
||||
>taMinorTick.length : any
|
||||
>taMinorTick : any
|
||||
>length : any
|
||||
>0 : number
|
||||
|
||||
tsize + taTitleGap;
|
||||
>tsize : any
|
||||
>taTitleGap : any
|
||||
|
||||
axisVector = { x: isRtl ? -1 : 1, y: 0 }; // chart mirroring
|
||||
>axisVector = { x: isRtl ? -1 : 1, y: 0 } : { x: number; y: number; }
|
||||
>axisVector : any
|
||||
>{ x: isRtl ? -1 : 1, y: 0 } : { x: number; y: number; }
|
||||
>x : number
|
||||
>isRtl ? -1 : 1 : number
|
||||
>isRtl : any
|
||||
>-1 : number
|
||||
>1 : number
|
||||
>1 : number
|
||||
>y : number
|
||||
>0 : number
|
||||
|
||||
switch (rotation) {
|
||||
>rotation : number
|
||||
|
||||
default:
|
||||
if (rotation < (90 - centerAnchorLimit)) {
|
||||
>rotation < (90 - centerAnchorLimit) : boolean
|
||||
>rotation : number
|
||||
>(90 - centerAnchorLimit) : number
|
||||
>90 - centerAnchorLimit : number
|
||||
>90 : number
|
||||
>centerAnchorLimit : any
|
||||
|
||||
labelOffset.y = leftBottom ? size : 0;
|
||||
>labelOffset.y = leftBottom ? size : 0 : any
|
||||
>labelOffset.y : any
|
||||
>labelOffset : any
|
||||
>y : any
|
||||
>leftBottom ? size : 0 : any
|
||||
>leftBottom : boolean
|
||||
>size : any
|
||||
>0 : number
|
||||
|
||||
} else if (rotation < (90 + centerAnchorLimit)) {
|
||||
>rotation < (90 + centerAnchorLimit) : boolean
|
||||
>rotation : number
|
||||
>(90 + centerAnchorLimit) : any
|
||||
>90 + centerAnchorLimit : any
|
||||
>90 : number
|
||||
>centerAnchorLimit : any
|
||||
|
||||
labelOffset.x = -size * 0.4;
|
||||
>labelOffset.x = -size * 0.4 : number
|
||||
>labelOffset.x : any
|
||||
>labelOffset : any
|
||||
>x : any
|
||||
>-size * 0.4 : number
|
||||
>-size : number
|
||||
>size : any
|
||||
>0.4 : number
|
||||
|
||||
} else if (rotation < 180) {
|
||||
>rotation < 180 : boolean
|
||||
>rotation : number
|
||||
>180 : number
|
||||
|
||||
labelOffset.y = leftBottom ? 0 : -size;
|
||||
>labelOffset.y = leftBottom ? 0 : -size : number
|
||||
>labelOffset.y : any
|
||||
>labelOffset : any
|
||||
>y : any
|
||||
>leftBottom ? 0 : -size : number
|
||||
>leftBottom : boolean
|
||||
>0 : number
|
||||
>-size : number
|
||||
>size : any
|
||||
|
||||
} else if (rotation < (270 - centerAnchorLimit)) {
|
||||
>rotation < (270 - centerAnchorLimit) : boolean
|
||||
>rotation : number
|
||||
>(270 - centerAnchorLimit) : number
|
||||
>270 - centerAnchorLimit : number
|
||||
>270 : number
|
||||
>centerAnchorLimit : any
|
||||
|
||||
labelOffset.y = leftBottom ? 0 : -size;
|
||||
>labelOffset.y = leftBottom ? 0 : -size : number
|
||||
>labelOffset.y : any
|
||||
>labelOffset : any
|
||||
>y : any
|
||||
>leftBottom ? 0 : -size : number
|
||||
>leftBottom : boolean
|
||||
>0 : number
|
||||
>-size : number
|
||||
>size : any
|
||||
|
||||
} else if (rotation < (270 + centerAnchorLimit)) {
|
||||
>rotation < (270 + centerAnchorLimit) : boolean
|
||||
>rotation : number
|
||||
>(270 + centerAnchorLimit) : any
|
||||
>270 + centerAnchorLimit : any
|
||||
>270 : number
|
||||
>centerAnchorLimit : any
|
||||
|
||||
labelOffset.y = leftBottom ? size * 0.4 : 0;
|
||||
>labelOffset.y = leftBottom ? size * 0.4 : 0 : number
|
||||
>labelOffset.y : any
|
||||
>labelOffset : any
|
||||
>y : any
|
||||
>leftBottom ? size * 0.4 : 0 : number
|
||||
>leftBottom : boolean
|
||||
>size * 0.4 : number
|
||||
>size : any
|
||||
>0.4 : number
|
||||
>0 : number
|
||||
|
||||
} else {
|
||||
labelOffset.y = leftBottom ? size : 0;
|
||||
>labelOffset.y = leftBottom ? size : 0 : any
|
||||
>labelOffset.y : any
|
||||
>labelOffset : any
|
||||
>y : any
|
||||
>leftBottom ? size : 0 : any
|
||||
>leftBottom : boolean
|
||||
>size : any
|
||||
>0 : number
|
||||
}
|
||||
}
|
||||
|
||||
titleRotation = (taTitleOrientation && taTitleOrientation == "away") ? 180 : 0;
|
||||
>titleRotation = (taTitleOrientation && taTitleOrientation == "away") ? 180 : 0 : number
|
||||
>titleRotation : number
|
||||
>(taTitleOrientation && taTitleOrientation == "away") ? 180 : 0 : number
|
||||
>(taTitleOrientation && taTitleOrientation == "away") : boolean
|
||||
>taTitleOrientation && taTitleOrientation == "away" : boolean
|
||||
>taTitleOrientation : any
|
||||
>taTitleOrientation == "away" : boolean
|
||||
>taTitleOrientation : any
|
||||
>"away" : string
|
||||
>180 : number
|
||||
>0 : number
|
||||
|
||||
titlePos.y = offsets.t - titleOffset + (titleRotation ? 0 : tsize);
|
||||
>titlePos.y = offsets.t - titleOffset + (titleRotation ? 0 : tsize) : any
|
||||
>titlePos.y : any
|
||||
>titlePos : any
|
||||
>y : any
|
||||
>offsets.t - titleOffset + (titleRotation ? 0 : tsize) : any
|
||||
>offsets.t - titleOffset : number
|
||||
>offsets.t : any
|
||||
>offsets : any
|
||||
>t : any
|
||||
>titleOffset : any
|
||||
>(titleRotation ? 0 : tsize) : any
|
||||
>titleRotation ? 0 : tsize : any
|
||||
>titleRotation : number
|
||||
>0 : number
|
||||
>tsize : any
|
||||
|
||||
switch (labelAlign) {
|
||||
>labelAlign : any
|
||||
|
||||
case "start":
|
||||
>"start" : string
|
||||
|
||||
labelAlign = "end";
|
||||
>labelAlign = "end" : string
|
||||
>labelAlign : any
|
||||
>"end" : string
|
||||
|
||||
break;
|
||||
case "end":
|
||||
>"end" : string
|
||||
|
||||
labelAlign = "start";
|
||||
>labelAlign = "start" : string
|
||||
>labelAlign : any
|
||||
>"start" : string
|
||||
|
||||
break;
|
||||
case "middle":
|
||||
>"middle" : string
|
||||
|
||||
labelOffset.y -= size;
|
||||
>labelOffset.y -= size : number
|
||||
>labelOffset.y : any
|
||||
>labelOffset : any
|
||||
>y : any
|
||||
>size : any
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
let _ = rotation;
|
||||
>_ : number
|
||||
>rotation : number
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ else {
|
||||
if (typeof x !== "number") {
|
||||
>typeof x !== "number" : boolean
|
||||
>typeof x : string
|
||||
>x : number | string
|
||||
>x : number | string | E | V
|
||||
>"number" : string
|
||||
|
||||
x; // string
|
||||
@@ -35,6 +35,6 @@ if (typeof x !== "number") {
|
||||
}
|
||||
else {
|
||||
x; // number|E|V
|
||||
>x : number
|
||||
>x : number | E | V
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'stri
|
||||
>(typeof strOrBool === 'boolean') : boolean
|
||||
>typeof strOrBool === 'boolean' : boolean
|
||||
>typeof strOrBool : string
|
||||
>strOrBool : string | boolean
|
||||
>strOrBool : boolean | string
|
||||
>'boolean' : string
|
||||
>strOrBool : boolean
|
||||
>false : boolean
|
||||
@@ -56,7 +56,7 @@ if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'stri
|
||||
>(typeof strOrBool !== 'string') : boolean
|
||||
>typeof strOrBool !== 'string' : boolean
|
||||
>typeof strOrBool : string
|
||||
>strOrBool : string | boolean
|
||||
>strOrBool : boolean | string
|
||||
>'string' : string
|
||||
>strOrBool : boolean
|
||||
>false : boolean
|
||||
@@ -94,7 +94,7 @@ if ((typeof strOrBool !== 'string' && !strOrBool) || typeof strOrBool !== 'boole
|
||||
>(typeof strOrBool === 'boolean') : boolean
|
||||
>typeof strOrBool === 'boolean' : boolean
|
||||
>typeof strOrBool : string
|
||||
>strOrBool : string | boolean
|
||||
>strOrBool : boolean | string
|
||||
>'boolean' : string
|
||||
>strOrBool : boolean
|
||||
>false : boolean
|
||||
@@ -116,7 +116,7 @@ if ((typeof strOrBool !== 'string' && !strOrBool) || typeof strOrBool !== 'boole
|
||||
>(typeof strOrBool !== 'string') : boolean
|
||||
>typeof strOrBool !== 'string' : boolean
|
||||
>typeof strOrBool : string
|
||||
>strOrBool : string | boolean
|
||||
>strOrBool : boolean | string
|
||||
>'string' : string
|
||||
>strOrBool : boolean
|
||||
>false : boolean
|
||||
|
||||
@@ -23,7 +23,7 @@ if (typeof stringOrNumber === "number" && typeof stringOrNumber !== "number") {
|
||||
>typeof stringOrNumber === "number" && typeof stringOrNumber !== "number" : boolean
|
||||
>typeof stringOrNumber === "number" : boolean
|
||||
>typeof stringOrNumber : string
|
||||
>stringOrNumber : number | string
|
||||
>stringOrNumber : string | number
|
||||
>"number" : string
|
||||
>typeof stringOrNumber !== "number" : boolean
|
||||
>typeof stringOrNumber : string
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// @strictNullChecks: true
|
||||
|
||||
// Repro for #8401
|
||||
|
||||
function f(dim, offsets, arr, acommon, centerAnchorLimit, g, has, lin) {
|
||||
var isRtl = this._isRtl(); // chart mirroring
|
||||
// prepare variable
|
||||
var o = this.opt, ta = this.chart.theme.axis, position = o.position,
|
||||
leftBottom = position !== "rightOrTop", rotation = o.rotation % 360,
|
||||
start, stop, titlePos, titleRotation = 0, titleOffset, axisVector, tickVector, anchorOffset, labelOffset, labelAlign,
|
||||
labelGap = this.chart.theme.axis.tick.labelGap,
|
||||
taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font),
|
||||
taTitleFont = o.titleFont || (ta.title && ta.title.font),
|
||||
taFontColor = o.fontColor || (ta.majorTick && ta.majorTick.fontColor) || (ta.tick && ta.tick.fontColor) || "black",
|
||||
taTitleFontColor = o.titleFontColor || (ta.title && ta.title.fontColor) || "black",
|
||||
taTitleGap = (o.titleGap == 0) ? 0 : o.titleGap || (ta.title && ta.title.gap) || 15,
|
||||
taTitleOrientation = o.titleOrientation || (ta.title && ta.title.orientation) || "axis",
|
||||
taMajorTick = this.chart.theme.getTick("major", o),
|
||||
taMinorTick = this.chart.theme.getTick("minor", o),
|
||||
taMicroTick = this.chart.theme.getTick("micro", o),
|
||||
|
||||
taStroke = "stroke" in o ? o.stroke : ta.stroke,
|
||||
size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
|
||||
cosr = Math.abs(Math.cos(rotation * Math.PI / 180)),
|
||||
sinr = Math.abs(Math.sin(rotation * Math.PI / 180)),
|
||||
tsize = taTitleFont ? g.normalizedLength(g.splitFontString(taTitleFont).size) : 0;
|
||||
if (rotation < 0) {
|
||||
rotation += 360;
|
||||
}
|
||||
var cachedLabelW = this._getMaxLabelSize();
|
||||
cachedLabelW = cachedLabelW && cachedLabelW.majLabelW;
|
||||
titleOffset = size * cosr + (cachedLabelW || 0) * sinr + labelGap + Math.max(taMajorTick.length > 0 ? taMajorTick.length : 0,
|
||||
taMinorTick.length > 0 ? taMinorTick.length : 0) +
|
||||
tsize + taTitleGap;
|
||||
axisVector = { x: isRtl ? -1 : 1, y: 0 }; // chart mirroring
|
||||
switch (rotation) {
|
||||
default:
|
||||
if (rotation < (90 - centerAnchorLimit)) {
|
||||
labelOffset.y = leftBottom ? size : 0;
|
||||
} else if (rotation < (90 + centerAnchorLimit)) {
|
||||
labelOffset.x = -size * 0.4;
|
||||
} else if (rotation < 180) {
|
||||
labelOffset.y = leftBottom ? 0 : -size;
|
||||
} else if (rotation < (270 - centerAnchorLimit)) {
|
||||
labelOffset.y = leftBottom ? 0 : -size;
|
||||
} else if (rotation < (270 + centerAnchorLimit)) {
|
||||
labelOffset.y = leftBottom ? size * 0.4 : 0;
|
||||
} else {
|
||||
labelOffset.y = leftBottom ? size : 0;
|
||||
}
|
||||
}
|
||||
|
||||
titleRotation = (taTitleOrientation && taTitleOrientation == "away") ? 180 : 0;
|
||||
titlePos.y = offsets.t - titleOffset + (titleRotation ? 0 : tsize);
|
||||
switch (labelAlign) {
|
||||
case "start":
|
||||
labelAlign = "end";
|
||||
break;
|
||||
case "end":
|
||||
labelAlign = "start";
|
||||
break;
|
||||
case "middle":
|
||||
labelOffset.y -= size;
|
||||
break;
|
||||
}
|
||||
|
||||
let _ = rotation;
|
||||
}
|
||||
Reference in New Issue
Block a user