rokucommunity / brighterscript

A superset of Roku's BrightScript language
MIT License
160 stars 46 forks source link

Namespaces that import each other can cause a circular dependency issue #377

Closed chrisdp closed 3 years ago

chrisdp commented 3 years ago
RangeError: Maximum call stack size exceeded
    at Program.getFileByPathAbsolute (/Users/chris/.vscode/extensions/rokucommunity.brightscript-2.17.9/node_modules/brighterscript/dist/Program.js:321:26)
    at BrsFile.resolveTypedef (/Users/chris/.vscode/extensions/rokucommunity.brightscript-2.17.9/node_modules/brighterscript/dist/files/BrsFile.js:116:41)
    at EventEmitter.<anonymous> (/Users/chris/.vscode/extensions/rokucommunity.brightscript-2.17.9/node_modules/brighterscript/dist/files/BrsFile.js:129:18)
    at EventEmitter.emit (/Users/chris/.vscode/extensions/rokucommunity.brightscript-2.17.9/node_modules/eventemitter3/index.js:202:33)
    at DependencyGraph.emit (/Users/chris/.vscode/extensions/rokucommunity.brightscript-2.17.9/node_modules/brighterscript/dist/DependencyGraph.js:79:30)
    at EventEmitter.<anonymous> (/Users/chris/.vscode/extensions/rokucommunity.brightscript-2.17.9/node_modules/brighterscript/dist/DependencyGraph.js:114:28)
    at EventEmitter.emit (/Users/chris/.vscode/extensions/rokucommunity.brightscript-2.17.9/node_modules/eventemitter3/index.js:202:33)
    at DependencyGraph.emit (/Users/chris/.vscode/extensions/rokucommunity.brightscript-2.17.9/node_modules/brighterscript/dist/DependencyGraph.js:79:30)
    at EventEmitter.<anonymous> (/Users/chris/.vscode/extensions/rokucommunity.brightscript-2.17.9/node_modules/brighterscript/dist/DependencyGraph.js:114:28)
    at EventEmitter.emit (/Users/chris/.vscode/extensions/rokucommunity.brightscript-2.17.9/node_modules/eventemitter3/index.js:202:33)
[11:02:55:1670 AM]  Validating project
[11:02:55:1670 AM]  Validating project finished. (0.37ms)

Example: you have a namespace called Types and a namespace called Getter Getter uses Types to validate object types. So for example Getter.Boolean(object, "path.in.object") will use Types.isBoolean(value) under the hood and Types internally might use Getter.<type>() under the hood for safe object traversal. As a result they import each other leading to the above crash.

TwitchBronBron commented 3 years ago

This actually has nothing to do with namespaces, it's caused by circular imports. This test will cause it too:

it('circular reference does not cause stack overflow', () => {
    program.addOrReplaceFile('components/a.bs', `
        import "b.bs"
    `);
    program.addOrReplaceFile('components/b.bs', `
        import "a.bs"
    `);

    //this is the test. if validation succeeds, there's no stack overflow
    program.validate();
});