Skip to content
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

[4.2.2] Compiler crash with null pointer in tsc.js: isWeakType resolved.callSignatures is null #42942

Closed
paztis opened this issue Feb 24, 2021 · 30 comments
Assignees
Labels
Needs More Info The issue still hasn't been fully clarified

Comments

@paztis
Copy link

paztis commented Feb 24, 2021

Bug Report

πŸ”Ž Search Terms

resolved.callSignatures

πŸ•— Version & Regression Information

  • This is a crash
  • This changed between versions 4.1.0 and 4.2.2

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

// We can quickly address your report if:
//  - The code sample is short. Nearly all TypeScript bugs can be demonstrated in 20-30 lines of code!
//  - It doesn't use external libraries. These are often issues with the type definitions rather than TypeScript bugs.
//  - The incorrectness of the behavior is readily apparent from reading the sample.
// Reports are slower to investigate if:
//  - We have to pare too much extraneous code.
//  - We have to clone a large repo and validate that the problem isn't elsewhere.
//  - The sample is confusing or doesn't clearly demonstrate what's wrong.

source code:

function isWeakType(type) {
    if (type.flags & 524288) {
        var resolved = resolveStructuredTypeMembers(type);
        return resolved.callSignatures.length === 0 && resolved.constructSignatures.length === 0 &&
            !resolved.stringIndexInfo && !resolved.numberIndexInfo &&
            resolved.properties.length > 0 &&
            ts.every(resolved.properties, function (p) { return !!(p.flags & 16777216); });
    }
    if (type.flags & 2097152) {
        return ts.every(type.types, isWeakType);
    }
    return false;
}

error log:

TypeError: Cannot read property 'length' of undefined
    at isWeakType (/Users/jeromeh/Workspaces/experience-core/digitalexp-ui-base/node_modules/typescript/lib/tsc.js:50733:48)
    at isRelatedTo (/Users/jeromeh/Workspaces/experience-core/digitalexp-ui-base/node_modules/typescript/lib/tsc.js:49252:58)
    at checkTypeRelatedTo (/Users/jeromeh/Workspaces/experience-core/digitalexp-ui-base/node_modules/typescript/lib/tsc.js:48974:26)
    at isTypeRelatedTo (/Users/jeromeh/Workspaces/experience-core/digitalexp-ui-base/node_modules/typescript/lib/tsc.js:48938:24)
    at removeSubtypes (/Users/jeromeh/Workspaces/experience-core/digitalexp-ui-base/node_modules/typescript/lib/tsc.js:46041:33)
    at getUnionType (/Users/jeromeh/Workspaces/experience-core/digitalexp-ui-base/node_modules/typescript/lib/tsc.js:46131:26)
    at getWidenedTypeForAssignmentDeclaration (/Users/jeromeh/Workspaces/experience-core/digitalexp-ui-base/node_modules/typescript/lib/tsc.js:42011:28)
    at getTypeOfFuncClassEnumModuleWorker (/Users/jeromeh/Workspaces/experience-core/digitalexp-ui-base/node_modules/typescript/lib/tsc.js:42497:34)
    at getTypeOfFuncClassEnumModule (/Users/jeromeh/Workspaces/experience-core/digitalexp-ui-base/node_modules/typescript/lib/tsc.js:42476:51)
    at getTypeOfSymbol (/Users/jeromeh/Workspaces/experience-core/digitalexp-ui-base/node_modules/typescript/lib/tsc.js:42579:24)

value of the resolved variable at crash time:

Type {
  flags: 524288,
  id: 5978,
  objectFlags: 16,
  symbol: <ref *1> Symbol {
    flags: 33554960,
    escapedName: '_extends',
    declarations: [ [Node] ],
    valueDeclaration: Node {
      pos: 0,
      end: 479,
      kind: 251,
      id: 5476,
      flags: 131072,
      modifierFlagsCache: 536870912,
      transformFlags: 1052704,
      parent: [Node],
      original: undefined,
      decorators: undefined,
      modifiers: undefined,
      symbol: [Symbol],
      localSymbol: undefined,
      locals: Map(0) {},
      nextContainer: [Node],
      name: [Identifier],
      typeParameters: undefined,
      parameters: [Array],
      type: undefined,
      body: [Node],
      asteriskToken: undefined,
      returnFlowNode: [Object],
      jsDocCache: []
    },
    id: undefined,
    mergeId: undefined,
    parent: undefined,
    checkFlags: 0,
    exports: Map(2) { 'default' => [Symbol], '___esModule' => [Symbol] },
    cjsExportMerged: [Circular *1],
    type: Type {
      flags: 524288,
      id: 5976,
      objectFlags: 16,
      symbol: [Circular *1],
      members: [Map],
      properties: undefined,
      callSignatures: undefined,
      constructSignatures: undefined,
      stringIndexInfo: undefined,
      numberIndexInfo: undefined
    },
    resolvedExports: Map(2) { 'default' => [Symbol], '___esModule' => [Symbol] }
  },
  members: Map(2) {
    'default' => Symbol {
      flags: 2097152,
      escapedName: 'default',
      declarations: [Array],
      valueDeclaration: undefined,
      id: 6422,
      mergeId: undefined,
      parent: [Symbol]
    },
    '___esModule' => Symbol {
      flags: 1048580,
      escapedName: '___esModule',
      declarations: [Array],
      valueDeclaration: [Node],
      id: undefined,
      mergeId: undefined,
      parent: [Symbol]
    }
  },
  properties: [
    Symbol {
      flags: 2097152,
      escapedName: 'default',
      declarations: [Array],
      valueDeclaration: undefined,
      id: 6422,
      mergeId: undefined,
      parent: [Symbol]
    },
    Symbol {
      flags: 1048580,
      escapedName: '___esModule',
      declarations: [Array],
      valueDeclaration: [Node],
      id: undefined,
      mergeId: undefined,
      parent: [Symbol]
    }
  ],
  callSignatures: undefined,
  constructSignatures: undefined,
  stringIndexInfo: undefined,
  numberIndexInfo: undefined
}

value of resolved.symbol.declarations[0]:
seems to came from @babel/runtime (in v7.13.7 on my node_modules)

<ref *1> Node {
  pos: 0,
  end: 479,
  kind: 251,
  id: 5476,
  flags: 131072,
  modifierFlagsCache: 536870912,
  transformFlags: 1052704,
  parent: <ref *2> Node {
    pos: 0,
    end: 586,
    kind: 297,
    id: 5471,
    flags: 131072,
    modifierFlagsCache: 536870912,
    transformFlags: 32,
    parent: undefined,
    original: undefined,
    statements: [
      [Circular *1],
      [Node],
      [Node],
      pos: 0,
      end: 585,
      hasTrailingComma: false,
      transformFlags: 32
    ],
    endOfFileToken: Token {
      pos: 585,
      end: 586,
      kind: 1,
      id: 0,
      flags: 131072,
      transformFlags: 0,
      parent: [Circular *2]
    },
    fileName: '/Users/jeromeh/Workspaces/experience-core/digitalexp-ui-base/node_modules/@babel/runtime/helpers/extends/index.js',
    text: 'function _extends() {\n' +
      '  module.exports = _extends = Object.assign || function (target) {\n' +
      '    for (var i = 1; i < arguments.length; i++) {\n' +
      '      var source = arguments[i];\n' +
      '\n' +
      '      for (var key in source) {\n' +
      '        if (Object.prototype.hasOwnProperty.call(source, key)) {\n' +
      '          target[key] = source[key];\n' +
      '        }\n' +
      '      }\n' +
      '    }\n' +
      '\n' +
      '    return target;\n' +
      '  };\n' +
      '\n' +
      '  module.exports["default"] = module.exports, module.exports.__esModule = true;\n' +
      '  return _extends.apply(this, arguments);\n' +
      '}\n' +
      '\n' +
      'module.exports = _extends;\n' +
      'module.exports["default"] = module.exports, module.exports.__esModule = true;\n',
    languageVersion: 99,
    languageVariant: 1,
    scriptKind: 1,
    isDeclarationFile: false,
    hasNoDefaultLib: false,
    externalModuleIndicator: undefined,
    bindDiagnostics: [],
    bindSuggestionDiagnostics: undefined,
    pragmas: Map(0) {},
    checkJsDirective: undefined,
    referencedFiles: [],
    typeReferenceDirectives: [],
    libReferenceDirectives: [],
    amdDependencies: [],
    commentDirectives: undefined,
    nodeCount: 129,
    identifierCount: 48,
    identifiers: Map(17) {
      '_extends' => '_extends',
      'module' => 'module',
      'exports' => 'exports',
      'Object' => 'Object',
      'assign' => 'assign',
      'target' => 'target',
      'i' => 'i',
      'arguments' => 'arguments',
      'length' => 'length',
      'source' => 'source',
      'key' => 'key',
      'prototype' => 'prototype',
      'hasOwnProperty' => 'hasOwnProperty',
      'call' => 'call',
      'default' => 'default',
      '__esModule' => '__esModule',
      'apply' => 'apply'
    },
    parseDiagnostics: [],
    path: '/users/jeromeh/workspaces/experience-core/digitalexp-ui-base/node_modules/@babel/runtime/helpers/extends/index.js',
    resolvedPath: '/users/jeromeh/workspaces/experience-core/digitalexp-ui-base/node_modules/@babel/runtime/helpers/extends/index.js',
    originalFileName: '/Users/jeromeh/Workspaces/experience-core/digitalexp-ui-base/node_modules/@babel/runtime/helpers/extends/index.js',
    imports: [],
    moduleAugmentations: [],
    ambientModuleNames: [],
    resolvedModules: undefined,
    additionalSyntacticDiagnostics: [],
    locals: Map(2) { '_extends' => [Symbol], 'module' => [Symbol] },
    nextContainer: [Circular *1],
    commonJsModuleIndicator: Node {
      pos: 21,
      end: 353,
      kind: 216,
      id: 0,
      flags: 131072,
      modifierFlagsCache: 536870912,
      transformFlags: 32,
      parent: [Node],
      original: undefined,
      left: [Node],
      operatorToken: [Token],
      right: [Node],
      symbol: [Symbol]
    },
    symbol: Symbol {
      flags: 512,
      escapedName: '"/Users/jeromeh/Workspaces/experience-core/digitalexp-ui-base/node_modules/@babel/runtime/helpers/extends/index"',
      declarations: [Array],
      valueDeclaration: [Circular *2],
      id: undefined,
      mergeId: undefined,
      parent: undefined,
      exports: [Map]
    },
    symbolCount: 12,
    classifiableNames: Set(2) { 'export=', 'default' },
    jsDocCache: []
  },
  original: undefined,
  decorators: undefined,
  modifiers: undefined,
  symbol: Symbol {
    flags: 16,
    escapedName: '_extends',
    declarations: [ [Circular *1] ],
    valueDeclaration: [Circular *1],
    id: 6415,
    mergeId: 1689,
    parent: undefined,
    isReferenced: 1949695
  },
  localSymbol: undefined,
  locals: Map(0) {},
  nextContainer: <ref *3> Node {
    pos: 68,
    end: 353,
    kind: 208,
    id: 5472,
    flags: 131072,
    modifierFlagsCache: 536875008,
    transformFlags: 1048608,
    parent: Node {
      pos: 51,
      end: 353,
      kind: 216,
      id: 0,
      flags: 131072,
      modifierFlagsCache: 0,
      transformFlags: 32,
      parent: [Node],
      original: undefined,
      left: [Node],
      operatorToken: [Token],
      right: [Circular *3]
    },
    original: undefined,
    decorators: undefined,
    modifiers: undefined,
    symbol: Symbol {
      flags: 16,
      escapedName: '__function',
      declarations: [Array],
      valueDeclaration: [Circular *3],
      id: 6416,
      mergeId: undefined,
      parent: undefined
    },
    localSymbol: undefined,
    locals: Map(4) {
      'target' => [Symbol],
      'i' => [Symbol],
      'source' => [Symbol],
      'key' => [Symbol]
    },
    nextContainer: undefined,
    name: undefined,
    typeParameters: undefined,
    parameters: [
      [Node],
      pos: 79,
      end: 85,
      hasTrailingComma: false,
      transformFlags: 0
    ],
    type: undefined,
    body: Node {
      pos: 86,
      end: 353,
      kind: 230,
      id: 0,
      flags: 131072,
      modifierFlagsCache: 0,
      transformFlags: 1048608,
      parent: [Circular *3],
      original: undefined,
      statements: [Array],
      multiLine: true
    },
    asteriskToken: undefined,
    flowNode: { flags: 6208, antecedent: [Object], node: [Node] },
    returnFlowNode: { flags: 6152, antecedents: [Array], id: 81 },
    jsDocCache: []
  },
  name: Identifier {
    pos: 8,
    end: 17,
    kind: 78,
    id: 0,
    flags: 131072,
    transformFlags: 0,
    parent: [Circular *1],
    original: undefined,
    flowNode: { flags: 6146 },
    originalKeywordKind: undefined,
    escapedText: '_extends'
  },
  typeParameters: undefined,
  parameters: [ pos: 18, end: 18, hasTrailingComma: false, transformFlags: 0 ],
  type: undefined,
  body: Node {
    pos: 19,
    end: 479,
    kind: 230,
    id: 0,
    flags: 131072,
    modifierFlagsCache: 0,
    transformFlags: 1052704,
    parent: [Circular *1],
    original: undefined,
    statements: [
      [Node],
      [Node],
      [Node],
      pos: 21,
      end: 477,
      hasTrailingComma: false,
      transformFlags: 1052704
    ],
    multiLine: true
  },
  asteriskToken: undefined,
  returnFlowNode: {
    flags: 2064,
    antecedent: { flags: 2304, antecedent: [Object], node: [Node] },
    node: Node {
      pos: 401,
      end: 427,
      kind: 201,
      id: 0,
      flags: 131072,
      modifierFlagsCache: 536870912,
      transformFlags: 0,
      parent: [Node],
      original: undefined,
      expression: [Node],
      name: [Identifier],
      symbol: [Symbol],
      flowNode: [Object]
    }
  },
  jsDocCache: []
}

πŸ™ Actual behavior

Crash

πŸ™‚ Expected behavior

Don't crash

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Feb 24, 2021
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 4.2.2 milestone Feb 24, 2021
@andrewbranch
Copy link
Member

@paztis the β€œsource code” section of the bug report is supposed to be the code that makes TypeScript crash, not the TypeScript code that crashes. I might be able to reconstruct something from the debug dumps you provided, but it would be really helpful if you could describe how to trigger this crash.

@paztis
Copy link
Author

paztis commented Feb 24, 2021

yes I know

I've difficulties to identify the problematic piece of code but just found it.
in @babel/runtime/helpers/extends/index.js (v7.13.7)

function _extends() {
  module.exports = _extends = Object.assign || function (target) {
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i];

      for (var key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
          target[key] = source[key];
        }
      }
    }

    return target;
  };

  module.exports["default"] = module.exports, module.exports.__esModule = true;
  return _extends.apply(this, arguments);
}

module.exports = _extends;
module.exports["default"] = module.exports, module.exports.__esModule = true;

If I replace it with its mjs version tsc compilation pass
in @babel/runtime/helpers/extends/_index.mjs (v7.13.7)

export default function _extends() {
  _extends = Object.assign || function (target) {
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i];

      for (var key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
          target[key] = source[key];
        }
      }
    }

    return target;
  };

  return _extends.apply(this, arguments);
}

@andrewbranch
Copy link
Member

So just compiling that file causes the crash? Or does the crash start with something that imports and uses _extends?

@paztis
Copy link
Author

paztis commented Feb 24, 2021 via email

@andrewbranch
Copy link
Member

Can you at least tell me what your tsconfig is like? Clearly you’re compiling JS with checkJs, right? And I think there must be a maxNodeModulesDepth if this JS file is getting checked?

@paztis
Copy link
Author

paztis commented Feb 24, 2021

Sorry

Yes I add it:

{
  "compilerOptions": {
    "jsx": "react-jsx"
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    // Process & infer types from .js files.
    "allowJs": true,
    "maxNodeModuleJsDepth": 3,
    // Enable strictest settings like strictNullChecks & noImplicitAny.
    "strict": false,
    "noImplicitAny": true,
    "noImplicitReturns": true,
    // "noImplicitThis": true,
    "isolatedModules": false, // Disallow features that require cross-file information for emit.
    "esModuleInterop": true, // Import non-ES modules as default imports.
    "skipLibCheck": true, // Do not validate the dependencies definitions
    "experimentalDecorators": true,
    "suppressImplicitAnyIndexErrors": true,
    // resolution of dependencies/
    "resolveJsonModule": true,
    "baseUrl": "."
  }
}

@paztis
Copy link
Author

paztis commented Feb 24, 2021

here is a repo where I reproduce the defect
https://codesandbox.io/s/twilight-sound-ll66d?file=/tsconfig.json

Locally, with the same code I've the error, but don't know why not on codeSandbox

just run the command npm run build on it

extra info: node: v14.15.0, system: bigSur

@andrewbranch
Copy link
Member

Perfect, thank you!

@andrewbranch
Copy link
Member

Hmm nope, never mind, doesn’t repro for me.

@andrewbranch andrewbranch added Needs More Info The issue still hasn't been fully clarified and removed Bug A bug in TypeScript labels Feb 24, 2021
@paztis
Copy link
Author

paztis commented Feb 24, 2021

you've create this repo locally ?

It contains only 4 files: package.json, tsConfig.json, src/index.ts and src/js/problematicFile.js
Do npm install (or yarn install), then npm run build

@andrewbranch
Copy link
Member

Yes. I’ve copied it exactly from the codesandbox.

@paztis
Copy link
Author

paztis commented Feb 24, 2021

on wich OS are you ? I'm on mac
Someone else try to reproduce it and it was working when coming from codeSandbox,
but fails from this zip:

test-module.zip

@paztis
Copy link
Author

paztis commented Feb 24, 2021

ok I've update the codeSandbox: https://codesandbox.io/s/twilight-sound-ll66d
I was setting index.js instead of index.ts

you can test in now it fails everywhere

@nicolo-ribaudo
Copy link

I can now reproduce the error.

@andrewbranch If it helps, deleting lines 16 and 21 of https://unpkg.com/browse/@babel/runtime@7.13.7/helpers/extends/index.js from node_modules makes the error disappear.

@nicolo-ribaudo
Copy link

I managed to create a smaller example:

package.json
{
  "name": "test-module",
  "version": "1.0.0",
  "scripts": {
    "build": "tsc --outDir lib/"
  },
  "dependencies": {
    "typescript": "4.2.2"
  }
}
tsconfig.json
{
  "compilerOptions": {
    "allowJs": true,
    "esModuleInterop": true,
    "noEmit": true,
    "baseUrl": "."
  },
  "include": ["src"]
}
src/index.ts
import dep from "./dep.js";

dep();
src/dep.js
function fn() {}
module.exports = fn;
module.exports = fn;
module.exports["default"] = module.exports;

ts-error-2.zip

@paztis
Copy link
Author

paztis commented Feb 24, 2021

babel team reject the responsability of their code. they said it is 100% typescript defect

@nicolo-ribaudo
Copy link

nicolo-ribaudo commented Feb 24, 2021

@paztis My example above shows the error without any Babel code 🀷

Btw, I can reproduce this starting from TS 4.1.2

@andrewbranch
Copy link
Member

Already fixed in #42766.

@paztis
Copy link
Author

paztis commented Feb 25, 2021

Wait. It has been fixed just after the 4.2.2 publish 13 days ago ?
But it means fix will not be release in 4.2.3 but in 4.3.0 ?

As it is blocking here you're supposed to provide a patch version 4.2.3

@paztis
Copy link
Author

paztis commented Feb 25, 2021

How can we manage a workaround on this defect today ? I cannot modify babel source code... When is your fix supposed to be released ?

@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Feb 25, 2021

@paztis We'll put this into the next 4.2 release (4.2.3 4.3.2)

Edit: Disastrously confusing typo; thanks @andrewbranch

@paztis
Copy link
Author

paztis commented Feb 25, 2021 via email

@nicolo-ribaudo
Copy link

@paztis as a workaround downgrade @babel/runtime to 7.12, since it contains the file where TS crashes

@paztis
Copy link
Author

paztis commented Feb 25, 2021 via email

@paztis
Copy link
Author

paztis commented Mar 1, 2021

Sorry to bother you again
We limit the version of @babel/runtime to ~7.12.0, but lot of other modules are requiring the 7.13.0
We're in a big monolithic repository, and yarn hoist the most used version at root level.
It means we've not full control on it.

So we're in a blocking situation now.
Really not possible to cherry-pick your fix on a 4.2.3 patch ?

I don't see other solutions for now

@nicolo-ribaudo
Copy link

@paztis You can pin it for your deps adding

"resolutions": {
  "@babel/runtime": "~7.12.0"
}

@paztis
Copy link
Author

paztis commented Mar 1, 2021

Ok know this one, but I hope it will not cause conflicts with other modules that requires version different from 7 of babel
Because yarn will install then a 7.12 even if they require 6.8

@nicolo-ribaudo
Copy link

@babel/runtime only exist at version 7; it might cause problems in a few months after the Babel 8 release.

@paztis
Copy link
Author

paztis commented Mar 1, 2021

ok thanks for all these info
It means next month, Typescript 4.3.2 will be released, so it will be ok

jayaddison added a commit to openculinary/frontend that referenced this issue Mar 1, 2021
- Pin @babel/runtime per microsoft/TypeScript#42942

Add undeclared workbox dependencies

Add sqlite3 unit-testing dependency
@andrewbranch
Copy link
Member

It’s being released in 4.2.3 #42942 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs More Info The issue still hasn't been fully clarified
Projects
None yet
Development

No branches or pull requests

4 participants