Skip to content

fix receiver on calls of imported and exported functions - #35877

Merged
Ron Buckton (rbuckton) merged 5 commits into
microsoft:masterfrom
ajafff:import-implied-receiver
Mar 3, 2021
Merged

fix receiver on calls of imported and exported functions#35877
Ron Buckton (rbuckton) merged 5 commits into
microsoft:masterfrom
ajafff:import-implied-receiver

Conversation

@ajafff

Copy link
Copy Markdown
Contributor

@ljharb

Copy link
Copy Markdown
Contributor

I see a lot of fixture changes but none of the test cases from #35420 added - specifically, a this-sensitive exported function being both called bare, and also .called with an explicit receiver.

@ajafff

Copy link
Copy Markdown
ContributorAuthor

Jordan Harband (@ljharb) the vast majority of the tests only verifies the correct transpilation result by comparing with the baselines. You can see from the changed baselines that imported functions are now called indirectly, which fixes the issue with the receiver.
IMO it's not really necessary to verify the runtime behavior with a test that evaluates the transpiled code. However, if you or someone else has a strong opinion on that, I'll add a test that does it.

@ljharb

Copy link
Copy Markdown
Contributor

It's certainly not up to me, but the important thing is the correct runtime semantics of the code, not the specifics of what gets output, so it seems like those tests would be the important thing :-)

@ljharb

Copy link
Copy Markdown
Contributor

Nathan Shively-Sanders (@sandersn) 3.8.1 has come and gone (#35420 is listed as in that milestone), and this important bugfix hasn't gone out yet. any update?

@sandersn

Copy link
Copy Markdown
Member

Ron Buckton (@rbuckton) This is now scheduled for 4.0. Can you review this fix during the beta?

if (!isIdentifier(node.expression)) {
return node;
}
const newExpression = substituteExpressionIdentifier(node.expression);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The substitution for the identifier should be invoked by the printer, you shouldn't have to call it directly.

@ljharb

Copy link
Copy Markdown
Contributor

Ping again - i know this needs a rebase, but it’s a pretty critical bug fix.

@rbuckton

Copy link
Copy Markdown
Contributor

I've rebased this PR and made a few small updates. We may also want to consider doing the same thing for namespace exports:

namespaceX{exportfunctionfoo(this: unknown){console.log(this===X);}}namespaceX{foo();// compiles to `X.foo()`, so would print `true`}

Daniel Rosenwasser (@DanielRosenwasser) we should discuss this emit change at the next design meeting.

@rbuckton

Copy link
Copy Markdown
Contributor

I've updated this to support namespace exports as well. as its essentially a bug there too and I'd like to see how this change effects compiler performance (because we call a lot of functions on the ts namespace).

@rbuckton

Copy link
Copy Markdown
Contributor

TypeScript Bot (@typescript-bot) perf test

@typescript-bot

TypeScript Bot (typescript-bot) commented Feb 10, 2021

Copy link
Copy Markdown
Contributor

Heya Ron Buckton (@rbuckton), I've started to run the perf test suite on this PR at b788c09. You can monitor the build here.

Update: The results are in!

@typescript-bot

Copy link
Copy Markdown
Contributor

Ron Buckton (@rbuckton)
The results of the perf run you requested are in!

Here they are:

Comparison Report - master..35877

Metricmaster35877DeltaBestWorst
Angular - node (v10.16.3, x64)
Memory used345,618k (± 0.02%)345,624k (± 0.02%)+6k (+ 0.00%)345,493k345,769k
Parse Time1.92s (± 0.40%)1.91s (± 0.35%)-0.01s (- 0.31%)1.90s1.93s
Bind Time0.82s (± 0.60%)0.82s (± 0.41%)-0.00s (- 0.12%)0.82s0.83s
Check Time4.97s (± 0.41%)4.94s (± 0.52%)-0.04s (- 0.72%)4.88s4.99s
Emit Time5.28s (± 0.97%)5.55s (± 0.59%)+0.27s (+ 5.11%)5.50s5.65s
Total Time12.99s (± 0.38%)13.22s (± 0.39%)+0.23s (+ 1.77%)13.14s13.36s
Compiler-Unions - node (v10.16.3, x64)
Memory used214,523k (± 0.06%)215,489k (± 0.16%)+966k (+ 0.45%)214,155k215,876k
Parse Time0.78s (± 0.67%)0.77s (± 0.67%)-0.01s (- 1.03%)0.76s0.78s
Bind Time0.50s (± 1.34%)0.50s (± 0.98%)+0.01s (+ 1.41%)0.50s0.52s
Check Time10.65s (± 0.40%)10.66s (± 0.69%)+0.01s (+ 0.05%)10.52s10.80s
Emit Time2.35s (± 1.67%)2.51s (± 1.37%)+0.17s (+ 7.16%)2.46s2.58s
Total Time14.27s (± 0.38%)14.44s (± 0.64%)+0.17s (+ 1.19%)14.27s14.64s
Monaco - node (v10.16.3, x64)
Memory used355,251k (± 0.02%)355,289k (± 0.03%)+38k (+ 0.01%)355,060k355,589k
Parse Time1.55s (± 0.58%)1.55s (± 0.57%)-0.00s (- 0.06%)1.53s1.57s
Bind Time0.72s (± 0.55%)0.73s (± 1.30%)+0.01s (+ 0.83%)0.71s0.75s
Check Time5.09s (± 0.57%)5.11s (± 0.66%)+0.02s (+ 0.39%)5.04s5.20s
Emit Time2.79s (± 0.64%)2.87s (± 1.12%)+0.08s (+ 3.05%)2.83s2.97s
Total Time10.15s (± 0.32%)10.26s (± 0.41%)+0.11s (+ 1.08%)10.19s10.37s
TFS - node (v10.16.3, x64)
Memory used308,114k (± 0.02%)308,161k (± 0.01%)+47k (+ 0.02%)308,123k308,249k
Parse Time1.20s (± 0.63%)1.20s (± 0.63%)+0.00s (+ 0.08%)1.19s1.22s
Bind Time0.68s (± 0.49%)0.68s (± 0.66%)-0.00s (- 0.29%)0.67s0.69s
Check Time4.60s (± 0.57%)4.59s (± 0.63%)-0.01s (- 0.22%)4.54s4.65s
Emit Time2.94s (± 0.83%)3.01s (± 0.51%)+0.07s (+ 2.28%)2.97s3.04s
Total Time9.42s (± 0.38%)9.48s (± 0.31%)+0.05s (+ 0.58%)9.42s9.56s
material-ui - node (v10.16.3, x64)
Memory used495,626k (± 0.02%)495,544k (± 0.02%)-81k (- 0.02%)495,311k495,683k
Parse Time1.98s (± 0.39%)1.97s (± 0.53%)-0.01s (- 0.30%)1.95s2.00s
Bind Time0.65s (± 0.95%)0.65s (± 0.72%)-0.00s (- 0.15%)0.64s0.66s
Check Time13.95s (± 0.92%)13.93s (± 0.59%)-0.03s (- 0.19%)13.77s14.11s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time16.59s (± 0.77%)16.55s (± 0.51%)-0.04s (- 0.22%)16.39s16.74s
Angular - node (v12.1.0, x64)
Memory used323,177k (± 0.03%)323,238k (± 0.03%)+61k (+ 0.02%)323,024k323,441k
Parse Time1.90s (± 0.66%)1.90s (± 0.87%)+0.00s (+ 0.26%)1.86s1.93s
Bind Time0.80s (± 0.86%)0.80s (± 0.60%)+0.00s (+ 0.13%)0.79s0.81s
Check Time4.85s (± 0.63%)4.87s (± 1.32%)+0.02s (+ 0.39%)4.76s5.10s
Emit Time5.40s (± 0.54%)5.75s (± 0.43%)+0.36s (+ 6.62%)5.70s5.81s
Total Time12.94s (± 0.47%)13.32s (± 0.67%)+0.38s (+ 2.95%)13.12s13.60s
Compiler-Unions - node (v12.1.0, x64)
Memory used199,902k (± 0.05%)201,074k (± 0.06%)+1,173k (+ 0.59%)200,776k201,288k
Parse Time0.77s (± 0.67%)0.77s (± 0.80%)-0.00s (- 0.26%)0.76s0.78s
Bind Time0.50s (± 0.60%)0.50s (± 0.44%)+0.00s (+ 0.60%)0.50s0.51s
Check Time9.72s (± 1.02%)9.70s (± 1.16%)-0.02s (- 0.16%)9.55s10.07s
Emit Time2.34s (± 1.01%)2.56s (± 0.96%)+0.22s (+ 9.26%)2.51s2.62s
Total Time13.33s (± 0.73%)13.54s (± 0.87%)+0.21s (+ 1.57%)13.37s13.93s
Monaco - node (v12.1.0, x64)
Memory used337,476k (± 0.01%)337,500k (± 0.02%)+25k (+ 0.01%)337,357k337,652k
Parse Time1.53s (± 0.87%)1.53s (± 0.75%)+0.00s (+ 0.20%)1.50s1.55s
Bind Time0.70s (± 0.63%)0.70s (± 0.70%)+0.00s (+ 0.28%)0.69s0.71s
Check Time4.91s (± 0.48%)4.91s (± 0.45%)0.00s ( 0.00%)4.85s4.94s
Emit Time2.86s (± 0.57%)2.91s (± 0.67%)+0.05s (+ 1.64%)2.87s2.95s
Total Time10.00s (± 0.32%)10.06s (± 0.33%)+0.06s (+ 0.58%)10.00s10.13s
TFS - node (v12.1.0, x64)
Memory used292,351k (± 0.01%)292,332k (± 0.02%)-19k (- 0.01%)292,224k292,454k
Parse Time1.22s (± 0.69%)1.23s (± 0.50%)+0.01s (+ 0.66%)1.21s1.24s
Bind Time0.65s (± 0.34%)0.66s (± 0.88%)+0.01s (+ 0.92%)0.65s0.67s
Check Time4.50s (± 0.40%)4.51s (± 0.34%)+0.01s (+ 0.18%)4.49s4.55s
Emit Time2.96s (± 0.91%)3.02s (± 0.91%)+0.06s (+ 2.20%)2.95s3.09s
Total Time9.33s (± 0.37%)9.42s (± 0.43%)+0.09s (+ 0.92%)9.33s9.51s
material-ui - node (v12.1.0, x64)
Memory used472,776k (± 0.01%)472,809k (± 0.01%)+33k (+ 0.01%)472,724k472,892k
Parse Time1.99s (± 0.51%)2.00s (± 0.60%)+0.01s (+ 0.70%)1.97s2.03s
Bind Time0.64s (± 0.35%)0.64s (± 1.18%)+0.00s (+ 0.47%)0.62s0.66s
Check Time12.49s (± 0.70%)12.49s (± 0.72%)-0.00s (- 0.04%)12.33s12.72s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time15.12s (± 0.58%)15.13s (± 0.59%)+0.01s (+ 0.07%)14.98s15.35s
Angular - node (v14.15.1, x64)
Memory used321,828k (± 0.01%)321,910k (± 0.01%)+82k (+ 0.03%)321,851k321,993k
Parse Time1.90s (± 0.55%)1.90s (± 0.54%)+0.00s (+ 0.05%)1.88s1.92s
Bind Time0.84s (± 0.43%)0.84s (± 0.81%)+0.00s (+ 0.12%)0.84s0.87s
Check Time4.83s (± 0.38%)4.86s (± 0.43%)+0.03s (+ 0.60%)4.83s4.91s
Emit Time5.48s (± 0.77%)5.83s (± 0.51%)+0.35s (+ 6.46%)5.79s5.93s
Total Time13.05s (± 0.49%)13.44s (± 0.39%)+0.39s (+ 2.96%)13.35s13.63s
Compiler-Unions - node (v14.15.1, x64)
Memory used199,870k (± 0.38%)200,674k (± 0.10%)+804k (+ 0.40%)200,098k200,928k
Parse Time0.79s (± 0.62%)0.79s (± 0.43%)-0.00s (- 0.13%)0.79s0.80s
Bind Time0.53s (± 0.42%)0.53s (± 0.56%)-0.00s (- 0.56%)0.52s0.53s
Check Time9.68s (± 0.56%)9.68s (± 0.81%)-0.00s (- 0.01%)9.54s9.93s
Emit Time2.34s (± 1.04%)2.54s (± 1.48%)+0.20s (+ 8.49%)2.48s2.63s
Total Time13.35s (± 0.48%)13.55s (± 0.53%)+0.20s (+ 1.48%)13.39s13.76s
Monaco - node (v14.15.1, x64)
Memory used336,849k (± 0.01%)336,929k (± 0.00%)+80k (+ 0.02%)336,901k336,961k
Parse Time1.55s (± 0.58%)1.55s (± 0.64%)+0.00s (+ 0.13%)1.53s1.57s
Bind Time0.73s (± 0.71%)0.73s (± 0.64%)+0.00s (+ 0.14%)0.72s0.74s
Check Time4.85s (± 0.61%)4.85s (± 0.48%)-0.00s (- 0.08%)4.80s4.91s
Emit Time2.91s (± 0.41%)3.00s (± 0.86%)+0.08s (+ 2.85%)2.96s3.08s
Total Time10.05s (± 0.39%)10.12s (± 0.45%)+0.08s (+ 0.78%)10.06s10.28s
TFS - node (v14.15.1, x64)
Memory used291,545k (± 0.00%)291,547k (± 0.01%)+2k (+ 0.00%)291,518k291,588k
Parse Time1.24s (± 0.99%)1.24s (± 1.23%)+0.00s (+ 0.24%)1.22s1.29s
Bind Time0.69s (± 0.64%)0.69s (± 0.84%)+0.00s (+ 0.14%)0.68s0.71s
Check Time4.50s (± 0.62%)4.50s (± 0.41%)+0.01s (+ 0.16%)4.45s4.54s
Emit Time3.03s (± 0.46%)3.13s (± 0.70%)+0.09s (+ 3.13%)3.08s3.18s
Total Time9.46s (± 0.30%)9.57s (± 0.37%)+0.11s (+ 1.17%)9.51s9.66s
material-ui - node (v14.15.1, x64)
Memory used471,401k (± 0.06%)471,503k (± 0.01%)+102k (+ 0.02%)471,437k471,554k
Parse Time2.06s (± 0.78%)2.05s (± 0.71%)-0.00s (- 0.19%)2.02s2.08s
Bind Time0.70s (± 0.74%)0.70s (± 0.64%)-0.00s (- 0.43%)0.69s0.71s
Check Time12.63s (± 0.83%)12.55s (± 1.53%)-0.07s (- 0.59%)12.38s13.31s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time15.38s (± 0.75%)15.30s (± 1.31%)-0.08s (- 0.54%)15.11s16.09s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-198-generic
Architecturex64
Available Memory16 GB
Available Memory7 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v10.16.3, x64)
  • node (v12.1.0, x64)
  • node (v14.15.1, x64)
Scenarios
  • Angular - node (v10.16.3, x64)
  • Angular - node (v12.1.0, x64)
  • Angular - node (v14.15.1, x64)
  • Compiler-Unions - node (v10.16.3, x64)
  • Compiler-Unions - node (v12.1.0, x64)
  • Compiler-Unions - node (v14.15.1, x64)
  • Monaco - node (v10.16.3, x64)
  • Monaco - node (v12.1.0, x64)
  • Monaco - node (v14.15.1, x64)
  • TFS - node (v10.16.3, x64)
  • TFS - node (v12.1.0, x64)
  • TFS - node (v14.15.1, x64)
  • material-ui - node (v10.16.3, x64)
  • material-ui - node (v12.1.0, x64)
  • material-ui - node (v14.15.1, x64)
BenchmarkNameIterations
Current3587710
Baselinemaster10

@rbuckton

Copy link
Copy Markdown
Contributor

TypeScript Bot (@typescript-bot) pack this

@typescript-bot

TypeScript Bot (typescript-bot) commented Feb 12, 2021

Copy link
Copy Markdown
Contributor

Heya Ron Buckton (@rbuckton), I've started to run the tarball bundle task on this PR at b788c09. You can monitor the build here.

@typescript-bot

TypeScript Bot (typescript-bot) commented Feb 12, 2021

Copy link
Copy Markdown
Contributor

Hey Ron Buckton (@rbuckton), I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:

{
"devDependencies": {
"typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/95810/artifacts?artifactName=tgz&fileId=F8AD257B669FDE703D7FF39DE9A54CE25327D7236435DF39341C2F15BD09C00802&fileName=/typescript-4.3.0-insiders.20210212.tgz"
}
}

and then running npm install.


There is also a playground for this build and an npm module you can use via "typescript": "npm:@typescript-deploys/pr-build@4.3.0-pr-35877-13".;

@rbuckton

Copy link
Copy Markdown
Contributor

Per discussion with Ryan Cavanaugh (@RyanCavanaugh) today, I'm going to revert the change for namespaces for the time being.

# Conflicts:
#	tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.js
@rbuckton

Ron Buckton (rbuckton) commented Mar 3, 2021

Copy link
Copy Markdown
Contributor

Hmm. build is failing for a unit test that doesn't exist anymore...

Ah, that's a typo in the externalModules.ts test.

@rbuckton
Ron Buckton (rbuckton) merged commit 7751ecb into microsoft:masterMar 3, 2021
@rbuckton

Copy link
Copy Markdown
Contributor

It looks like we will need to revert this change until TS 4.4 while we investigate the significant performance regression this causes during emit. In the worst case, we may need to land this behind a flag to opt-in to the change, though ideally I can find a mitigation for the performance regression so that we can land this without a flag.

@ljharb

Copy link
Copy Markdown
Contributor

Reverting this seems like it will restore the active breakage on a number of my shims like Promise.allSettled, where the module.exports function explicitly relies on having an undefined receiver.

Why does a performance regression matter when compared to runtime breakage?

@ljharb

Copy link
Copy Markdown
Contributor

Ron Buckton (@rbuckton) ping, TS is severely broken without this fix; any update on restoring it?

@DanielRosenwasser

Copy link
Copy Markdown
Member

We re-re-discussed this at #44555.

We've always tried to balance reasonable/canonical-looking emit and general UX with exact semantics of the spec. We're not ready to sacrifice that and also impose an emit overhead on everyone, especially when performance is something we're really working to improve. If we can find some optimizations that make this "free-ish", we'd feel better about this feature; otherwise, we'll need to put it behind a flag (like --downlevelIteration, --useDefinedForClassFields, etc.).

Why does a performance regression matter when compared to runtime breakage?

The bigger risk here is actually imposing runtime breakage on existing users who accidentally came to rely on the existing behavior. Given that, the safer thing might actually be to put it behind a flag.

@ljharb

Copy link
Copy Markdown
Contributor

Daniel Rosenwasser (@DanielRosenwasser) so you’re worried about users who expect that, defying the way it works everywhere else in the JS exosystem, an exported function’s receiver will be the module namespace object when called as a bare function? I’d love to understand what code is relying on this behavior.

@RyanCavanaugh

Copy link
Copy Markdown
Member

so you’re worried about users who expect that, defying the way it works everywhere else in the JS exosystem

Yes. Improved spec compliance has caused problems before, e.g. when we made exports immutable/nonenumerable (jasmine/jasmine#1817, #38568).

@ljharb

Copy link
Copy Markdown
Contributor

Alright - can it at least be landed behind a flag, so i can tell users how to unbreak their applications?

@RyanCavanaugh

Copy link
Copy Markdown
Member

We're definitely going to figure something out, just trying to work out what exactly that is

@rbuckton

Copy link
Copy Markdown
Contributor

We were able to re-land this in #44624 in a way that does not significantly impact emit performance.

@ljharb

Copy link
Copy Markdown
Contributor

That's amazing, great to hear!

@microsoftMicrosoft (microsoft) locked as resolved and limited conversation to collaborators Oct 21, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

For Milestone BugPRs that fix a bug with a specific milestone

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Functions wrapped in __importDefault with allowSyntheticDefaultImports emit incorrect function calls

7 participants

@ajafff@ljharb@sandersn@rbuckton@typescript-bot@DanielRosenwasser@RyanCavanaugh