React JavaScript modules not running in strict mode
🐛 bug report
Preflight Checklist
- [x] I have read the Contributing Guidelines for this project.
- [x] I agree to follow the Code of Conduct that this project adheres to.
- [x] I have searched the issue tracker for an issue that matches the one I want to file, without success.
Description of the problem
JavaScript files (ie: JavaScript modules) created in a React.js Sandbox don't run their JavaScript code in strict mode as they should be.
How has this issue affected you? What are you trying to accomplish?
This issue has caused bugs and issues within programs that users who are familiar with modules wouldn't expect to see. It causes the JavaScript code within the module to behave unexpectedly as it's being run in sloppy mode instead of strict mode. There are a number of different things that change when strict mode is applied to code, so having the module run in sloppy modes when it should be running in strict mode causes head-scratching and unusual bugs.
I found this issue when answering this StackOverflow question about certain JavaScript behaviour.
To Reproduce
- Create a React.js sandbox.
- In a new file (eg:
Test.js) add some JavaScript code that would fail or behave differently in sloppy mode vs strict mode, eg:
// Test.js
(function() {console.log(this)}).call(undefined);
- Import this new file in
index.js,import "./Test.js"so that the code within it will run. - When ran, view the console. You'll see that
windowis logged, butundefinedshould have been logged as the module should be run in strict mode. Instead, it is running in sloppy mode and so we getwindow.
Link to sandbox: link
Analysis:
I did some of my own digging. The bug seems to be caused by some code within refresh-transpiler.ts on line number 189. What happens is that when the module is transpiled, a "use strict"; directive is added to the top of the source code (which is fine and expected), but then the linked piece of code wraps the transpiled code in a try {} block. This then causes the "use strict"; not to take effect as it's not at the top of the source code anymore, and use strict doesn't apply to regular code blocks {}.
Your Environment
| Software | Name/Version |
|---|---|
| Сodesandbox | 560d0f63c |
| Browser | Chrome Version 104.0.5112.101 (Official Build) (x86_64) |
| Operating System | macOS Catalina |
I wonder if this could be a general issue as well? Because when we want to execute code, we also wrap that code itself inside a function, like this:
(function(module, exports, require) {
... your code ...
})
And then execute that code to call the function with the globals. I wonder if that also "erases" the "use strict";. Or is "use strict"; allowed at the start of a function?
@CompuIves "use strict"; is allowed to be at the top of a fuction, so when CodeSandbox wraps it in a function like you've shown the code within that function will run in strict mode as expected.
I guess the problem is more general than just React if there are other parts of the CodeSandbox source that are wrapping the transpiled code in anything other than a function, function constructor or eval call. eg, in the case above, the code is wrapped in a try {} block so we lose the "use strict";
I think a potential fix for this issue is to wrap the source code in an IIFE so that "use strict" is preserved, but I'll let you guys decide on the best way to resolve this :)