microsoft/TypeScript

Prototype assignment doesn't work on default-assigned constructor functions

minestarks opened this issue · 1 comments

Bug seen in actual VS customer code.

TypeScript Version: 3.9.2

Search Terms: ES5 class javascript prototype assignment constructor function

Expected behavior: In the example below, I expect the test.class properties include the one from the prototype. The behavior shouldn't depend on whether or not test.class was default-assigned or not.

Actual behavior: The prototype assignment doesn't seem to work when default assignment is used. @sandersn thinks this is a bug but isn't surprised.

Related Issues: #39166 from same user code

Code

var test = {};

test.class = test.class || function (name) {

    function getName() {
        return name;
    }

    this.name = getName();
}

test.class.prototype = {
    add: function (i) {
    }
}; 

var t = new test.class("test");
t.name
t.add // EXPECTED: Binds to `add` from the prototype, ACTUAL: doesn't


//
// Same pattern works with a straightforward assignment:
//

var test2 = {};

// Removed `test.class ||` 
test2.class = function (name) {

    function getName() {
        return name;
    }

    this.name = getName();
}

test2.class.prototype = {
    add: function (i) {
    }
}; 

var t2 = new test2.class("test");
t2.name
t2.add // ACTUAL: `add` bound correctly
Compiler Options
{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "checkJs": true,
    "allowJs": true,
    "declaration": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": 2,
    "target": "ES2017",
    "jsx": "React",
    "module": "ESNext"
  }
}

Playground Link: Provided

getAssignedClassSymbol, which looks up members of prototype, is wrong for default-assigned constructor functions, and returns undefined incorrectly.