codesandbox / codesandbox-client

An online IDE for rapid web development
https://codesandbox.io
Other
13.11k stars 2.29k forks source link

React JavaScript modules not running in strict mode #6845

Open npar0005 opened 2 years ago

npar0005 commented 2 years ago

🐛 bug report

Preflight Checklist

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

  1. Create a React.js sandbox.
  2. 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);
  3. Import this new file in index.js, import "./Test.js" so that the code within it will run.
  4. When ran, view the console. You'll see that window is logged, but undefined should have been logged as the module should be run in strict mode. Instead, it is running in sloppy mode and so we get window.

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
CompuIves commented 2 years ago

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?

npar0005 commented 2 years ago

@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 :)