diff --git a/tsc/internal/binder/nameresolver.go b/tsc/internal/binder/nameresolver.go index 4d0db524946cb..8c69fe1553bfd 100644 --- a/tsc/internal/binder/nameresolver.go +++ b/tsc/internal/binder/nameresolver.go @@ -74,8 +74,8 @@ loop: lastLocation.Kind == ast.KindJSDocReturnTag || lastLocation.Kind == ast.KindTypeParameter) } - if meaning&result.Flags()&ast.SymbolFlagsVariable != 0 { - // expression inside parameter will lookup as normal variable scope when targeting es2015+ + if meaning&result.Flags()&(ast.SymbolFlagsVariable|ast.SymbolFlagsFunction) != 0 { + // Expressions inside parameters use the outer scope for declarations in the function body. if r.useOuterVariableScopeInParameter(result, location, lastLocation) { useResult = false } else if result.Flags()&ast.SymbolFlagsFunctionScopedVariable != 0 { diff --git a/tsc/testdata/baselines/reference/compiler/defaultParameterBodyFunctionScope.errors.txt b/tsc/testdata/baselines/reference/compiler/defaultParameterBodyFunctionScope.errors.txt new file mode 100644 index 0000000000000..6f55fb08303b0 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/defaultParameterBodyFunctionScope.errors.txt @@ -0,0 +1,37 @@ +defaultParameterBodyFunctionScope.ts(19,37): error TS2304: Cannot find name 'missing'. + + +==== defaultParameterBodyFunctionScope.ts (1 errors) ==== + const styles = { root: "outer" }; + + export function read(value = styles.root) { + function styles() {} + styles(); + return value; + } + + export function readClosure(value = () => styles.root) { + function styles() {} + return value(); + } + + export function readDestructured({ value = styles.root } = {}) { + function styles() {} + return value; + } + + export function readMissing(value = missing) { + ~~~~~~~ +!!! error TS2304: Cannot find name 'missing'. + function missing() {} + return value; + } + + export function readParameter(styles = { root: "parameter" }, value = styles.root) { + return value; + } + + export const readNamed = function named(value = named) { + return value; + }; + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/defaultParameterBodyFunctionScope.js b/tsc/testdata/baselines/reference/compiler/defaultParameterBodyFunctionScope.js new file mode 100644 index 0000000000000..41ae37b313a23 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/defaultParameterBodyFunctionScope.js @@ -0,0 +1,60 @@ +//// [tests/cases/compiler/defaultParameterBodyFunctionScope.ts] //// + +//// [defaultParameterBodyFunctionScope.ts] +const styles = { root: "outer" }; + +export function read(value = styles.root) { + function styles() {} + styles(); + return value; +} + +export function readClosure(value = () => styles.root) { + function styles() {} + return value(); +} + +export function readDestructured({ value = styles.root } = {}) { + function styles() {} + return value; +} + +export function readMissing(value = missing) { + function missing() {} + return value; +} + +export function readParameter(styles = { root: "parameter" }, value = styles.root) { + return value; +} + +export const readNamed = function named(value = named) { + return value; +}; + + +//// [defaultParameterBodyFunctionScope.js] +const styles = { root: "outer" }; +export function read(value = styles.root) { + function styles() { } + styles(); + return value; +} +export function readClosure(value = () => styles.root) { + function styles() { } + return value(); +} +export function readDestructured({ value = styles.root } = {}) { + function styles() { } + return value; +} +export function readMissing(value = missing) { + function missing() { } + return value; +} +export function readParameter(styles = { root: "parameter" }, value = styles.root) { + return value; +} +export const readNamed = function named(value = named) { + return value; +}; diff --git a/tsc/testdata/baselines/reference/compiler/defaultParameterBodyFunctionScope.symbols b/tsc/testdata/baselines/reference/compiler/defaultParameterBodyFunctionScope.symbols new file mode 100644 index 0000000000000..c2eceabe5a1ec --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/defaultParameterBodyFunctionScope.symbols @@ -0,0 +1,87 @@ +//// [tests/cases/compiler/defaultParameterBodyFunctionScope.ts] //// + +=== defaultParameterBodyFunctionScope.ts === +const styles = { root: "outer" }; +>styles : Symbol(styles, Decl(defaultParameterBodyFunctionScope.ts, 0, 5)) +>root : Symbol(root, Decl(defaultParameterBodyFunctionScope.ts, 0, 16)) + +export function read(value = styles.root) { +>read : Symbol(read, Decl(defaultParameterBodyFunctionScope.ts, 0, 33)) +>value : Symbol(value, Decl(defaultParameterBodyFunctionScope.ts, 2, 21)) +>styles.root : Symbol(root, Decl(defaultParameterBodyFunctionScope.ts, 0, 16)) +>styles : Symbol(styles, Decl(defaultParameterBodyFunctionScope.ts, 0, 5)) +>root : Symbol(root, Decl(defaultParameterBodyFunctionScope.ts, 0, 16)) + + function styles() {} +>styles : Symbol(styles, Decl(defaultParameterBodyFunctionScope.ts, 2, 43)) + + styles(); +>styles : Symbol(styles, Decl(defaultParameterBodyFunctionScope.ts, 2, 43)) + + return value; +>value : Symbol(value, Decl(defaultParameterBodyFunctionScope.ts, 2, 21)) +} + +export function readClosure(value = () => styles.root) { +>readClosure : Symbol(readClosure, Decl(defaultParameterBodyFunctionScope.ts, 6, 1)) +>value : Symbol(value, Decl(defaultParameterBodyFunctionScope.ts, 8, 28)) +>styles.root : Symbol(root, Decl(defaultParameterBodyFunctionScope.ts, 0, 16)) +>styles : Symbol(styles, Decl(defaultParameterBodyFunctionScope.ts, 0, 5)) +>root : Symbol(root, Decl(defaultParameterBodyFunctionScope.ts, 0, 16)) + + function styles() {} +>styles : Symbol(styles, Decl(defaultParameterBodyFunctionScope.ts, 8, 56)) + + return value(); +>value : Symbol(value, Decl(defaultParameterBodyFunctionScope.ts, 8, 28)) +} + +export function readDestructured({ value = styles.root } = {}) { +>readDestructured : Symbol(readDestructured, Decl(defaultParameterBodyFunctionScope.ts, 11, 1)) +>value : Symbol(value, Decl(defaultParameterBodyFunctionScope.ts, 13, 34)) +>styles.root : Symbol(root, Decl(defaultParameterBodyFunctionScope.ts, 0, 16)) +>styles : Symbol(styles, Decl(defaultParameterBodyFunctionScope.ts, 0, 5)) +>root : Symbol(root, Decl(defaultParameterBodyFunctionScope.ts, 0, 16)) + + function styles() {} +>styles : Symbol(styles, Decl(defaultParameterBodyFunctionScope.ts, 13, 64)) + + return value; +>value : Symbol(value, Decl(defaultParameterBodyFunctionScope.ts, 13, 34)) +} + +export function readMissing(value = missing) { +>readMissing : Symbol(readMissing, Decl(defaultParameterBodyFunctionScope.ts, 16, 1)) +>value : Symbol(value, Decl(defaultParameterBodyFunctionScope.ts, 18, 28)) + + function missing() {} +>missing : Symbol(missing, Decl(defaultParameterBodyFunctionScope.ts, 18, 46)) + + return value; +>value : Symbol(value, Decl(defaultParameterBodyFunctionScope.ts, 18, 28)) +} + +export function readParameter(styles = { root: "parameter" }, value = styles.root) { +>readParameter : Symbol(readParameter, Decl(defaultParameterBodyFunctionScope.ts, 21, 1)) +>styles : Symbol(styles, Decl(defaultParameterBodyFunctionScope.ts, 23, 30)) +>root : Symbol(root, Decl(defaultParameterBodyFunctionScope.ts, 23, 40)) +>value : Symbol(value, Decl(defaultParameterBodyFunctionScope.ts, 23, 61)) +>styles.root : Symbol(root, Decl(defaultParameterBodyFunctionScope.ts, 23, 40)) +>styles : Symbol(styles, Decl(defaultParameterBodyFunctionScope.ts, 23, 30)) +>root : Symbol(root, Decl(defaultParameterBodyFunctionScope.ts, 23, 40)) + + return value; +>value : Symbol(value, Decl(defaultParameterBodyFunctionScope.ts, 23, 61)) +} + +export const readNamed = function named(value = named) { +>readNamed : Symbol(readNamed, Decl(defaultParameterBodyFunctionScope.ts, 27, 12)) +>named : Symbol(named, Decl(defaultParameterBodyFunctionScope.ts, 27, 24)) +>value : Symbol(value, Decl(defaultParameterBodyFunctionScope.ts, 27, 40)) +>named : Symbol(named, Decl(defaultParameterBodyFunctionScope.ts, 27, 24)) + + return value; +>value : Symbol(value, Decl(defaultParameterBodyFunctionScope.ts, 27, 40)) + +}; + diff --git a/tsc/testdata/baselines/reference/compiler/defaultParameterBodyFunctionScope.types b/tsc/testdata/baselines/reference/compiler/defaultParameterBodyFunctionScope.types new file mode 100644 index 0000000000000..0b64b83ba538b --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/defaultParameterBodyFunctionScope.types @@ -0,0 +1,97 @@ +//// [tests/cases/compiler/defaultParameterBodyFunctionScope.ts] //// + +=== defaultParameterBodyFunctionScope.ts === +const styles = { root: "outer" }; +>styles : { root: string; } +>{ root: "outer" } : { root: string; } +>root : string +>"outer" : "outer" + +export function read(value = styles.root) { +>read : (value?: string) => string +>value : string +>styles.root : string +>styles : { root: string; } +>root : string + + function styles() {} +>styles : () => void + + styles(); +>styles() : void +>styles : () => void + + return value; +>value : string +} + +export function readClosure(value = () => styles.root) { +>readClosure : (value?: () => string) => string +>value : () => string +>() => styles.root : () => string +>styles.root : string +>styles : { root: string; } +>root : string + + function styles() {} +>styles : () => void + + return value(); +>value() : string +>value : () => string +} + +export function readDestructured({ value = styles.root } = {}) { +>readDestructured : ({ value }?: { value?: string | undefined; }) => string +>value : string +>styles.root : string +>styles : { root: string; } +>root : string +>{} : {} + + function styles() {} +>styles : () => void + + return value; +>value : string +} + +export function readMissing(value = missing) { +>readMissing : (value?: any) => any +>value : any +>missing : any + + function missing() {} +>missing : () => void + + return value; +>value : any +} + +export function readParameter(styles = { root: "parameter" }, value = styles.root) { +>readParameter : (styles?: { root: string; }, value?: string) => string +>styles : { root: string; } +>{ root: "parameter" } : { root: string; } +>root : string +>"parameter" : "parameter" +>value : string +>styles.root : string +>styles : { root: string; } +>root : string + + return value; +>value : string +} + +export const readNamed = function named(value = named) { +>readNamed : (value?: typeof readNamed) => typeof readNamed +>function named(value = named) { return value;} : (value?: typeof readNamed) => typeof readNamed +>named : (value?: typeof readNamed) => typeof readNamed +>value : (value?: typeof readNamed) => typeof readNamed +>named : (value?: typeof readNamed) => typeof readNamed + + return value; +>value : (value?: typeof readNamed) => typeof readNamed + +}; + diff --git a/tsc/testdata/tests/cases/compiler/defaultParameterBodyFunctionScope.ts b/tsc/testdata/tests/cases/compiler/defaultParameterBodyFunctionScope.ts new file mode 100644 index 0000000000000..30cc64616d933 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/defaultParameterBodyFunctionScope.ts @@ -0,0 +1,33 @@ +// @target: esnext +// @strict: true + +const styles = { root: "outer" }; + +export function read(value = styles.root) { + function styles() {} + styles(); + return value; +} + +export function readClosure(value = () => styles.root) { + function styles() {} + return value(); +} + +export function readDestructured({ value = styles.root } = {}) { + function styles() {} + return value; +} + +export function readMissing(value = missing) { + function missing() {} + return value; +} + +export function readParameter(styles = { root: "parameter" }, value = styles.root) { + return value; +} + +export const readNamed = function named(value = named) { + return value; +};