Skip to content

In a namespace exported classes, functions, enums, and nested namespaces should be readonly #16720

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16724,12 +16724,13 @@ namespace ts {
// Variables declared with 'const'
// Get accessors without matching set accessors
// Enum members
// Classes, functions, enums, and nested namespaces (these are properties if defined in a namespace)
// Unions and intersections of the above (unions and intersections eagerly set isReadonly on creation)
return !!(getCheckFlags(symbol) & CheckFlags.Readonly ||
symbol.flags & SymbolFlags.Property && getDeclarationModifierFlagsFromSymbol(symbol) & ModifierFlags.Readonly ||
symbol.flags & SymbolFlags.Variable && getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Const ||
symbol.flags & SymbolFlags.Accessor && !(symbol.flags & SymbolFlags.SetAccessor) ||
symbol.flags & SymbolFlags.EnumMember);
symbol.flags & (SymbolFlags.EnumMember | SymbolFlags.Class | SymbolFlags.Function | SymbolFlags.Enum | SymbolFlags.Namespace));
}

function isReferenceToReadonlyEntity(expr: Expression, symbol: Symbol): boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,22 @@ tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesize
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(15,1): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(17,1): error TS2539: Cannot assign to 'M' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(18,2): error TS2539: Cannot assign to 'M' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(25,5): error TS2539: Cannot assign to 'M3' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(31,1): error TS2322: Type '{ x: string; }' is not assignable to type 'typeof M3'.
Types of property 'x' are incompatible.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(32,1): error TS2322: Type '{ x: string; }' is not assignable to type 'typeof M3'.
Types of property 'x' are incompatible.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(33,1): error TS2322: Type '{ x: string; }' is not assignable to type 'typeof M3'.
Types of property 'x' are incompatible.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(37,1): error TS2539: Cannot assign to 'fn' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(38,2): error TS2539: Cannot assign to 'fn' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(43,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(44,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(48,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(49,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(54,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(55,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(56,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(62,1): error TS2539: Cannot assign to 'E' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(63,2): error TS2539: Cannot assign to 'E' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(69,1): error TS2539: Cannot assign to 'C' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(70,2): error TS2539: Cannot assign to 'C' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(21,1): error TS2539: Cannot assign to 'fn' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(22,2): error TS2539: Cannot assign to 'fn' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(27,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(28,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(32,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(33,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(38,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(39,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(40,5): error TS2322: Type '""' is not assignable to type 'number'.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(46,1): error TS2539: Cannot assign to 'E' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(47,2): error TS2539: Cannot assign to 'E' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(53,1): error TS2539: Cannot assign to 'C' because it is not a variable.
tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts(54,2): error TS2539: Cannot assign to 'C' because it is not a variable.


==== tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts (24 errors) ====
==== tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesizedIdentifiers.ts (20 errors) ====
var x: number;
x = 3; // OK
(x) = 3; // OK
Expand Down Expand Up @@ -64,36 +54,6 @@ tests/cases/conformance/expressions/valuesAndReferences/assignmentToParenthesize
~
!!! error TS2539: Cannot assign to 'M' because it is not a variable.

module M2 {
export module M3 {
export var x: number;
}

M3 = { x: 3 }; // Error
~~
!!! error TS2539: Cannot assign to 'M3' because it is not a variable.
}
M2.M3 = { x: 3 }; // OK
(M2).M3 = { x: 3 }; // OK
(M2.M3) = { x: 3 }; // OK

M2.M3 = { x: '' }; // Error
~~~~~
!!! error TS2322: Type '{ x: string; }' is not assignable to type 'typeof M3'.
!!! error TS2322: Types of property 'x' are incompatible.
!!! error TS2322: Type 'string' is not assignable to type 'number'.
(M2).M3 = { x: '' }; // Error
~~~~~~~
!!! error TS2322: Type '{ x: string; }' is not assignable to type 'typeof M3'.
!!! error TS2322: Types of property 'x' are incompatible.
!!! error TS2322: Type 'string' is not assignable to type 'number'.
(M2.M3) = { x: '' }; // Error
~~~~~~~
!!! error TS2322: Type '{ x: string; }' is not assignable to type 'typeof M3'.
!!! error TS2322: Types of property 'x' are incompatible.
!!! error TS2322: Type 'string' is not assignable to type 'number'.


function fn() { }
fn = () => 3; // Bug 823548: Should be error (fn is not a reference)
~~
Expand Down
29 changes: 0 additions & 29 deletions tests/baselines/reference/assignmentToParenthesizedIdentifiers.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,6 @@ M.y = ''; // Error
M = { y: 3 }; // Error
(M) = { y: 3 }; // Error

module M2 {
export module M3 {
export var x: number;
}

M3 = { x: 3 }; // Error
}
M2.M3 = { x: 3 }; // OK
(M2).M3 = { x: 3 }; // OK
(M2.M3) = { x: 3 }; // OK

M2.M3 = { x: '' }; // Error
(M2).M3 = { x: '' }; // Error
(M2.M3) = { x: '' }; // Error


function fn() { }
fn = () => 3; // Bug 823548: Should be error (fn is not a reference)
(fn) = () => 3; // Should be error
Expand Down Expand Up @@ -88,19 +72,6 @@ M.y = ''; // Error
(M.y) = ''; // Error
M = { y: 3 }; // Error
(M) = { y: 3 }; // Error
var M2;
(function (M2) {
var M3;
(function (M3) {
})(M3 = M2.M3 || (M2.M3 = {}));
M3 = { x: 3 }; // Error
})(M2 || (M2 = {}));
M2.M3 = { x: 3 }; // OK
(M2).M3 = { x: 3 }; // OK
(M2.M3) = { x: 3 }; // OK
M2.M3 = { x: '' }; // Error
(M2).M3 = { x: '' }; // Error
(M2.M3) = { x: '' }; // Error
function fn() { }
fn = function () { return 3; }; // Bug 823548: Should be error (fn is not a reference)
(fn) = function () { return 3; }; // Should be error
Expand Down
59 changes: 59 additions & 0 deletions tests/baselines/reference/namespaceExportsAreReadonly.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
tests/cases/compiler/namespaceExportsAreReadonly.ts(19,3): error TS2540: Cannot assign to 'x' because it is a constant or a read-only property.
tests/cases/compiler/namespaceExportsAreReadonly.ts(21,3): error TS2540: Cannot assign to 'C' because it is a constant or a read-only property.
tests/cases/compiler/namespaceExportsAreReadonly.ts(24,3): error TS2540: Cannot assign to 'f' because it is a constant or a read-only property.
tests/cases/compiler/namespaceExportsAreReadonly.ts(28,3): error TS2540: Cannot assign to 'E' because it is a constant or a read-only property.
tests/cases/compiler/namespaceExportsAreReadonly.ts(33,3): error TS2540: Cannot assign to 'M' because it is a constant or a read-only property.


==== tests/cases/compiler/namespaceExportsAreReadonly.ts (5 errors) ====
namespace N {
export const x = 0;

export class C {}
export let D = class {}

export function f() {}
export let g = function() {}

export enum E {}
enum Ff {}
export let F = Ff;

export namespace M { export const y = 0; }
namespace Oo { export const y = 0; }
export let O = Oo;
}

N.x = 1; // Error
~
!!! error TS2540: Cannot assign to 'x' because it is a constant or a read-only property.

N.C = class {}; // Error
~
!!! error TS2540: Cannot assign to 'C' because it is a constant or a read-only property.
N.D = class {}; // OK

N.f = function() {} // Error
~
!!! error TS2540: Cannot assign to 'f' because it is a constant or a read-only property.
N.g = function() {} // OK

enum Ee {}
N.E = Ee; // Error
~
!!! error TS2540: Cannot assign to 'E' because it is a constant or a read-only property.
enum Ff {}
N.F = Ff; // OK

namespace Mm { export const y = 0; }
N.M = Mm; // Error
~
!!! error TS2540: Cannot assign to 'M' because it is a constant or a read-only property.
namespace Oo { export const y = 0; }
N.O = Oo; // OK

class K {
m() {}
}
new K().m = () => {}; // OK

116 changes: 116 additions & 0 deletions tests/baselines/reference/namespaceExportsAreReadonly.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//// [namespaceExportsAreReadonly.ts]
namespace N {
export const x = 0;

export class C {}
export let D = class {}

export function f() {}
export let g = function() {}

export enum E {}
enum Ff {}
export let F = Ff;

export namespace M { export const y = 0; }
namespace Oo { export const y = 0; }
export let O = Oo;
}

N.x = 1; // Error

N.C = class {}; // Error
N.D = class {}; // OK

N.f = function() {} // Error
N.g = function() {} // OK

enum Ee {}
N.E = Ee; // Error
enum Ff {}
N.F = Ff; // OK

namespace Mm { export const y = 0; }
N.M = Mm; // Error
namespace Oo { export const y = 0; }
N.O = Oo; // OK

class K {
m() {}
}
new K().m = () => {}; // OK


//// [namespaceExportsAreReadonly.js]
var N;
(function (N) {
N.x = 0;
var C = (function () {
function C() {
}
return C;
}());
N.C = C;
N.D = (function () {
function class_1() {
}
return class_1;
}());
function f() { }
N.f = f;
N.g = function () { };
var E;
(function (E) {
})(E = N.E || (N.E = {}));
var Ff;
(function (Ff) {
})(Ff || (Ff = {}));
N.F = Ff;
var M;
(function (M) {
M.y = 0;
})(M = N.M || (N.M = {}));
var Oo;
(function (Oo) {
Oo.y = 0;
})(Oo || (Oo = {}));
N.O = Oo;
})(N || (N = {}));
N.x = 1; // Error
N.C = (function () {
function class_2() {
}
return class_2;
}()); // Error
N.D = (function () {
function class_3() {
}
return class_3;
}()); // OK
N.f = function () { }; // Error
N.g = function () { }; // OK
var Ee;
(function (Ee) {
})(Ee || (Ee = {}));
N.E = Ee; // Error
var Ff;
(function (Ff) {
})(Ff || (Ff = {}));
N.F = Ff; // OK
var Mm;
(function (Mm) {
Mm.y = 0;
})(Mm || (Mm = {}));
N.M = Mm; // Error
var Oo;
(function (Oo) {
Oo.y = 0;
})(Oo || (Oo = {}));
N.O = Oo; // OK
var K = (function () {
function K() {
}
K.prototype.m = function () { };
return K;
}());
new K().m = function () { }; // OK
2 changes: 1 addition & 1 deletion tests/baselines/reference/nonInstantiatedModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ module M2 {
var p: { x: number; y: number; };
var p: M2.Point;

var p2: { Origin() : { x: number; y: number; } };
var p2: { readonly Origin: () => { x: number; y: number; } };
var p2: typeof M2.Point;

module M3 {
Expand Down
6 changes: 3 additions & 3 deletions tests/baselines/reference/nonInstantiatedModule.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ var p: M2.Point;
>M2 : Symbol(M2, Decl(nonInstantiatedModule.ts, 13, 13))
>Point : Symbol(M2.Point, Decl(nonInstantiatedModule.ts, 15, 11), Decl(nonInstantiatedModule.ts, 20, 5))

var p2: { Origin() : { x: number; y: number; } };
var p2: { readonly Origin: () => { x: number; y: number; } };
>p2 : Symbol(p2, Decl(nonInstantiatedModule.ts, 31, 3), Decl(nonInstantiatedModule.ts, 32, 3))
>Origin : Symbol(Origin, Decl(nonInstantiatedModule.ts, 31, 9))
>x : Symbol(x, Decl(nonInstantiatedModule.ts, 31, 22))
>y : Symbol(y, Decl(nonInstantiatedModule.ts, 31, 33))
>x : Symbol(x, Decl(nonInstantiatedModule.ts, 31, 34))
>y : Symbol(y, Decl(nonInstantiatedModule.ts, 31, 45))

var p2: typeof M2.Point;
>p2 : Symbol(p2, Decl(nonInstantiatedModule.ts, 31, 3), Decl(nonInstantiatedModule.ts, 32, 3))
Expand Down
6 changes: 3 additions & 3 deletions tests/baselines/reference/nonInstantiatedModule.types
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ var p: M2.Point;
>M2 : any
>Point : M2.Point

var p2: { Origin() : { x: number; y: number; } };
>p2 : { Origin(): { x: number; y: number; }; }
var p2: { readonly Origin: () => { x: number; y: number; } };
>p2 : { readonly Origin: () => { x: number; y: number; }; }
>Origin : () => { x: number; y: number; }
>x : number
>y : number

var p2: typeof M2.Point;
>p2 : { Origin(): { x: number; y: number; }; }
>p2 : { readonly Origin: () => { x: number; y: number; }; }
>M2.Point : typeof M2.Point
>M2 : typeof M2
>Point : typeof M2.Point
Expand Down
Loading