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

[Bug]: proxyquire can't load modules after window.open method is called #37404

Closed
3 tasks done
kyrylo-hrechykhin opened this issue Feb 24, 2023 · 21 comments · Fixed by #38754
Closed
3 tasks done

[Bug]: proxyquire can't load modules after window.open method is called #37404

kyrylo-hrechykhin opened this issue Feb 24, 2023 · 21 comments · Fixed by #38754

Comments

@kyrylo-hrechykhin
Copy link
Contributor

kyrylo-hrechykhin commented Feb 24, 2023

Preflight Checklist

Electron Version

23.0.0

What operating system are you using?

Windows

Operating System Version

Windows 11, Version22H2, OS Build 22621.1265

What arch are you using?

x64

Last Known Working Electron version

22.3.1

Expected Behavior

proxyquire should load modules as it does with electron version 22.3.1.

Actual Behavior

Attempt to use proxyquire in tests with electron of version 23 an higher leads to the following error message:

     TypeError: Script methods can only be called on script instances.
      at Script.runInThisContext (node:vm:129:12)
      at Object.runInThisContext (node:vm:313:38)
      at wrapSafe (node:internal/modules/cjs/loader:1083:15)
      at Module._compile (node:internal/modules/cjs/loader:1130:27)
      at Module._extensions..js (node:internal/modules/cjs/loader:1229:10)
      at require.extensions.<computed> (C:\work\proxyquire-test\node_modules\proxyquire\lib\proxyquire.js:311:43)
      at Module.load (node:internal/modules/cjs/loader:1044:32)
      at Module._load (node:internal/modules/cjs/loader:885:12)
      at f._load (node:electron/js2c/asar_bundle:2:13330)
      at o._load (node:electron/js2c/renderer_init:2:3109)
      at Module.require (node:internal/modules/cjs/loader:1068:19)
      at Proxyquire._withoutCache (C:\work\proxyquire-test\node_modules\proxyquire\lib\proxyquire.js:222:12)
      at Proxyquire.load (C:\work\proxyquire-test\node_modules\proxyquire\lib\proxyquire.js:129:15)
      at Context.<anonymous> (C:\work\proxyquire-test\test.spec.js:7:5)
      at callFn (C:\work\proxyquire-test\node_modules\mocha\lib\runnable.js:366:21)
      at Runnable.run (C:\work\proxyquire-test\node_modules\mocha\lib\runnable.js:354:5)
      at Runner.runTest (C:\work\proxyquire-test\node_modules\mocha\lib\runner.js:678:10)
      at C:\work\proxyquire-test\node_modules\mocha\lib\runner.js:801:12
      at next (C:\work\proxyquire-test\node_modules\mocha\lib\runner.js:593:14)
      at C:\work\proxyquire-test\node_modules\mocha\lib\runner.js:603:7
      at next (C:\work\proxyquire-test\node_modules\mocha\lib\runner.js:486:14)
      at Immediate._onImmediate (C:\work\proxyquire-test\node_modules\mocha\lib\runner.js:571:5)
      at process.processImmediate (node:internal/timers:471:21)

Testcase Gist URL

https://gist.github.com/kyrylo-hrechykhin/f0afe7c469145c51d4df39fbea97ec95

Additional Information

Workarounds:

  • avoid calling window.open method completely
  • separate electron-mocha runs to the one where window.open method is called and the one where proxyquire is used. If it happens in two different files, it is easy to do.

Details:

Issue is probably caused by node version upgrade in electron 23. But as it worked in electron 22, I consider it as a regression. I also could not reproduce this issue in non-electron environment.

Run testcase gist locally:

Run the following commands in the folder where all the files specified in the attached gist.

yarn
yarn start

Please upgrade/downgrade electron versions to see actual/expected results.

@kyrylo-hrechykhin
Copy link
Contributor Author

@zcbenz , @deepak1556 , could you please help analyzing this issue?
FYI: @miniak

@zcbenz
Copy link
Member

zcbenz commented Feb 27, 2023

To simplify the issue, following code is enough to trigger the bug:

const vm = require('node:vm');
const context = { x: 2 };
vm.createContext(context);

window.open('');
vm.runInContext('x += 40; var y = 17;', context);

This bug is still mysterious to me though.

@codebytere
Copy link
Member

codebytere commented Feb 28, 2023

@kyrylo-hrechykhin @zcbenz Blink assumes that all Contexts come with a ScriptState across the board, which is what's ultimately causing this issue. It's why we initially deprecated vm in the renderer process in #26087.

The stacktrace is as follows:

[96495:0228/141431.157160:FATAL:script_state.h(178)] Security CHECK failed: script_state. 
0   Electron Framework                  0x00000001198e005c base::debug::CollectStackTrace(void**, unsigned long) + 28
1   Electron Framework                  0x00000001198155b8 base::debug::StackTrace::StackTrace() + 24
2   Electron Framework                  0x000000011982bedc logging::LogMessage::~LogMessage() + 156
3   Electron Framework                  0x000000011b4b11ac blink::ScriptState::From(v8::Local<v8::Context>) + 148
4   Electron Framework                  0x000000011b4ec4f8 blink::WorldSafeV8ReferenceInternal::MaybeCheckCreationContextWorld(blink::DOMWrapperWorld const&, v8::Local<v8::Value>) + 52
5   Electron Framework                  0x000000011b4b36e4 blink::WorldSafeV8Reference<v8::Value>::WorldSafeV8Reference(v8::Isolate*, v8::Local<v8::Value>) + 212
6   Electron Framework                  0x000000011b4b006c blink::V8Initializer::MessageHandlerInMainThread(v8::Local<v8::Message>, v8::Local<v8::Value>) + 424
7   Electron Framework                  0x0000000116d7aeac v8::internal::MessageHandler::ReportMessageNoExceptions(v8::internal::Isolate*, v8::internal::MessageLocation const*, v8::internal::Handle<v8::internal::Object>, v8::Local<v8::Value>) + 852
8   Electron Framework                  0x0000000116d7a97c v8::internal::MessageHandler::ReportMessage(v8::internal::Isolate*, v8::internal::MessageLocation const*, v8::internal::Handle<v8::internal::JSMessageObject>) + 2140
9   Electron Framework                  0x0000000116d595a4 v8::internal::Isolate::ReportPendingMessages() + 1500
10  Electron Framework                  0x0000000116d2fc40 v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) + 5972
11  Electron Framework                  0x0000000116d30874 v8::internal::Execution::CallScript(v8::internal::Isolate*, v8::internal::Handle<v8::internal::JSFunction>, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>) + 520
12  Electron Framework                  0x00000001169df08c v8::Script::Run(v8::Local<v8::Context>, v8::Local<v8::Data>) + 1632
13  Electron Framework                  0x000000011b4b9318 blink::V8ScriptRunner::RunCompiledScript(v8::Isolate*, v8::Local<v8::Script>, v8::Local<v8::Data>, blink::ExecutionContext*) + 868
14  Electron Framework                  0x000000011b4b9b44 blink::V8ScriptRunner::CompileAndRunScript(blink::ScriptState*, blink::ClassicScript*, blink::ExecuteScriptPolicy, blink::V8ScriptRunner::RethrowErrorsOption) + 988
15  Electron Framework                  0x000000011c41f340 blink::ClassicScript::RunScriptOnScriptStateAndReturnValue(blink::ScriptState*, blink::ExecuteScriptPolicy, blink::V8ScriptRunner::RethrowErrorsOption) + 76
16  Electron Framework                  0x000000011c434b64 blink::Script::RunScript(blink::LocalDOMWindow*, blink::ExecuteScriptPolicy, blink::V8ScriptRunner::RethrowErrorsOption) + 276
17  Electron Framework                  0x000000011c43a314 blink::PendingScript::ExecuteScriptBlockInternal(blink::Script*, blink::ScriptElementBase*, bool, bool, bool, base::TimeTicks, bool) + 524
18  Electron Framework                  0x000000011c43a054 blink::PendingScript::ExecuteScriptBlock() + 692
19  Electron Framework                  0x000000011cabde18 blink::HTMLParserScriptRunner::ExecutePendingParserBlockingScriptAndDispatchEvent() + 188
20  Electron Framework                  0x000000011cabecec blink::HTMLParserScriptRunner::ExecuteParsingBlockingScripts() + 328
21  Electron Framework                  0x000000011cabedf0 blink::HTMLParserScriptRunner::ExecuteScriptsWaitingForLoad() + 100
22  Electron Framework                  0x000000011cad0ee0 blink::HTMLDocumentParser::NotifyScriptLoaded() + 176
23  Electron Framework                  0x000000011844b814 WTF::ThreadCheckingCallbackWrapper<base::OnceCallback<void ()>, void ()>::Run() + 80
24  Electron Framework                  0x000000011987df08 base::TaskAnnotator::RunTaskImpl(base::PendingTask&) + 296
25  Electron Framework                  0x00000001198a2554 base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(base::LazyNow*) + 1276
26  Electron Framework                  0x00000001198a1b9c base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() + 108
27  Electron Framework                  0x00000001198f3c8c base::MessagePumpCFRunLoopBase::RunWork() + 104
28  Electron Framework                  0x00000001198f2d04 base::mac::CallWithEHFrame(void () block_pointer) + 16
29  Electron Framework                  0x00000001198f3280 base::MessagePumpCFRunLoopBase::RunWorkSource(void*) + 68
30  CoreFoundation                      0x000000018ac25a08 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
31  CoreFoundation                      0x000000018ac2599c __CFRunLoopDoSource0 + 176
32  CoreFoundation                      0x000000018ac2570c __CFRunLoopDoSources0 + 244
33  CoreFoundation                      0x000000018ac24310 __CFRunLoopRun + 836
34  CoreFoundation                      0x000000018ac23878 CFRunLoopRunSpecific + 612
35  Foundation                          0x000000018bb2eab8 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212
36  Electron Framework                  0x00000001198f41fc base::MessagePumpNSRunLoop::DoRun(base::MessagePump::Delegate*) + 128
37  Electron Framework                  0x00000001198f2db8 base::MessagePumpCFRunLoopBase::Run(base::MessagePump::Delegate*) + 164
38  Electron Framework                  0x00000001198a3228 base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool, base::TimeDelta) + 452
39  Electron Framework                  0x000000011985af88 base::RunLoop::Run(base::Location const&) + 492
40  Electron Framework                  0x000000011df22814 content::RendererMain(content::MainFunctionParams) + 1336
41  Electron Framework                  0x000000011592af88 content::RunOtherNamedProcessTypeMain(std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char>> const&, content::MainFunctionParams, content::ContentMainDelegate*) + 692
42  Electron Framework                  0x000000011592bc5c content::ContentMainRunnerImpl::Run() + 712
43  Electron Framework                  0x000000011592a320 content::RunContentProcess(content::ContentMainParams, content::ContentMainRunner*) + 1016
44  Electron Framework                  0x000000011592a580 content::ContentMain(content::ContentMainParams) + 112
45  Electron Framework                  0x00000001155f2d50 ElectronMain + 128
46  Electron Helper (Renderer)          0x0000000100c44a00 main + 224
47  dyld                                0x000000018a81be50 start + 2544
Task trace:
0   Electron Framework                  0x000000011cabe184 blink::HTMLParserScriptRunner::PendingScriptFinished(blink::PendingScript*) + 208
1   Electron Framework                  0x0000000119c31d04 mojo::SimpleWatcher::Context::Notify(unsigned int, MojoHandleSignalsState, unsigned int) + 224
Crash keys:
  "blink_scheduler_async_stack" = "0x11CABE184 0x119C31D04"
  "v8_ro_space_firstpage_address" = "0x389700000000"
  "v8_isolate_address" = "0x138008000"
  "num-experiments" = "0"
  "platform" = "darwin"
  "process_type" = "renderer"
  "osarch" = "arm64"
  "pid" = "96495"
  "ptype" = "renderer"
Renderer process crashed - see https://www.electronjs.org/docs/tutorial/application-debugging for potential debugging information.

which confirms the above. Personally, I don't think there's really a good path forward here beyond to avoid tripping that faulty assumption in Blink (since patching whac-a-mole would not be a smart choice here), but i'm happy to be proven wrong!

@gpetrov
Copy link

gpetrov commented Mar 4, 2023

Getting the same error with just a simple require:

var Docker = require('dockerode')

TypeError: Script methods can only be called on script instances.
    at Script.runInThisContext (node:vm:129:12)
    at Object.runInThisContext (node:vm:313:38)
    at wrapSafe (node:internal/modules/cjs/loader:1083:15)
    at Module._compile (node:internal/modules/cjs/loader:1130:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1229:10)
    at Module.load (node:internal/modules/cjs/loader:1044:32)
    at Module._load (node:internal/modules/cjs/loader:885:12)
    at f._load (node:electron/js2c/asar_bundle:2:13330)
    at o._load (node:electron/js2c/renderer_init:2:3109)
    at Module.require (node:internal/modules/cjs/loader:1068:19)
    at require (node:internal/modules/cjs/helpers:103:18)

it is a major roadblock for us to upgrade to Electron 23+

@codebytere
Copy link
Member

codebytere commented Mar 5, 2023

@gpetrov this restriction/deprecation has existed in Electron for nearly a dozen versions - were you not seeing this before with the same userland code? It'd help if you provided a reproducible sample for us to run.

Edit: ah, i see the new aspect of this bug! I'll take a look this week - tracked it to 75d2caf

@codebytere codebytere self-assigned this Mar 5, 2023
@codebytere
Copy link
Member

codebytere commented Mar 6, 2023

@gpetrov a repro from you with dockerode would still be helpful! Some preliminary research shows this seems to affect vm scripts run after window.open('') specifically with no url.

@codebytere
Copy link
Member

codebytere commented Mar 6, 2023

Got a preliminary fix up: #37506 cc @zcbenz

@gpetrov
Copy link

gpetrov commented Mar 6, 2023

@codebytere will do my best to isolate the case. We do use window.open a lot but in this case the error happens just on the main window, somewhere after extensive js object creations and maybe some context switching. After that it happens in various modules not just dockerode

@gpetrov
Copy link

gpetrov commented Mar 6, 2023

@codebytere definately window.open related. When I have that the next require fails directly.

Also got a crash in during the testing, not sure if it is related:

https://sentry.wappler.io/share/issue/be27b0431aa54a5c8f8f668e72776458/

@gpetrov
Copy link

gpetrov commented Apr 1, 2023

@codebytere still happens in 23.2.1 - any news about merging the fix?

@gpetrov
Copy link

gpetrov commented May 4, 2023

Jitsi problem is also related, we have similar iframe contexts that the error occur.

Will the solution also fix those iframe problems @codebytere

@gpetrov
Copy link

gpetrov commented May 11, 2023

Got a preliminary fix up: #37506 cc @zcbenz

what happen to the fix? @codebytere and @zcbenz - the problem still persist in the latest Electron 23, 24 and 25

@gpetrov
Copy link

gpetrov commented Jun 14, 2023

@codebytere - finally I was able to isolate our use case for this bug! It was when creating dynamically iframes in the global scope! and those have full url as src and not about:blank.

So this code causes also the error:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <title>Hello World!</title>

    <script>

      function runTest() {
        console.log('START runTest')
        window.jQuery = window.$ = require('jquery');
      }

    </script>

  </head>
  <body>
    <h1>Hello World!</h1>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.

    <button onclick="runTest()">Run Test</button>

    <!-- You can also require other files to run in this process -->
    <script src="./renderer.js"></script>

    <script>

    //After creating dynamically iframe at the end of the body - all subsequential requires as this on in runTest() fail
    var iframe = document.createElement('iframe');
    iframe.src = 'iframe.html';

    document.body.appendChild(iframe);

    </script>
  </body>
</html>

Is this the same problem?

@codebytere
Copy link
Member

@gpetrov do you have a more reproducible sample than that? given it doesn't run as-is i want to make sure i'm checking the right thing against the fix!

@gpetrov
Copy link

gpetrov commented Jun 14, 2023

@codebytere sure here is my full sample:

iframe_require_bug.zip

just extract, do npm install, run it, press the runTest button and check the devtools

@codebytere
Copy link
Member

@gpetrov great news:

Screenshot 2023-06-14 at 9 24 34 PM

Same bug - no error on my fix branch

@gpetrov
Copy link

gpetrov commented Jun 14, 2023

@codebytere that is awesome!

With the same sample on 25.1.0 i get:

Screenshot 2023-06-14 at 21 45 14

So hope your fix gets merged quickly, as we need it desperately!

@zcbenz
Copy link
Member

zcbenz commented Jun 23, 2023

This issue seems to be consist of 2 separate bugs:

  1. Calling vm.runInContext after window.open would throw an exception from Node;
  2. Throwing an exception in a vm context would crash the exception handler in blink.

@KochiyaOcean
Copy link

This issue still leaves unfixed since no release version contains the fix

@gpetrov
Copy link

gpetrov commented Sep 22, 2023

@codebytere please reopen the issue as it isn't fixed yet. Or do we need to post a new issue?

@erikjalevik
Copy link

I ran into what looks like this issue in Electron 26, but seems fixed in 27.

(And hello again @gpetrov, seems we have all the same bugs!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment