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

Cannot find context with specified id" #286

Open
eNcacz opened this issue Jul 19, 2024 · 3 comments
Open

Cannot find context with specified id" #286

eNcacz opened this issue Jul 19, 2024 · 3 comments

Comments

@eNcacz
Copy link
Contributor

eNcacz commented Jul 19, 2024

I already reported this error as issue 263. The testcase from that issue now works well in 2.0.0-alpha.29, but the error still appears in my project.
So I prepared another testcase which is failing in 2.0.0-alpha.29.

We need these two html files:

browserFrameTestParent.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Scraper test page for Browser frame methods</title>
</head>
<body>
    <h1>Main Page</h1>
    <div id="parentContent" >This is parent content</div>
    <iframe id="testFrame" class="frameClass" src="browserFrameTestFrame.html"></iframe>
</body>
</html>

browserFrameTestFrame.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Scraper test page for Browser frame methods</title>
</head>
<body>
    <h2>This is the Frame Page 1</h2>
    <a id="changeTopDocument" href="doesntMatterFile.html" target="_top">Change whole page, not only the frame.</a>
</body>
</html>

And this is the test script:

import Hero from '@ulixee/hero-playground'

process.on('unhandledRejection', (reason, _) => {
    if (reason instanceof Error)
        console.error(`Unhandled Rejection: ${reason}`, {stack: reason.stack})
    else
        console.error(`Unhandled Rejection: ${reason}`)
    process.exit(1)
});

(async () => {
    const hero = new Hero()
    await hero.goto('http://localhost/~vaclav/ulixee/browserFrameTestParent.html')  // <- change this url
    await hero.waitForPaintingStable()

    const frameElem = await hero.document.getElementById("testFrame")
    const frameEnv = await hero.mainFrameEnvironment.getFrameEnvironment(frameElem)
    const anchor = await frameEnv.document.getElementById("changeTopDocument")
    await anchor.scrollIntoView({block: 'end', inline: 'nearest'})
    await anchor.$click('none')

    console.log('Now it will crash')
    await anchor.isConnected

    console.log('This will not be printed. The application crash on the line above.')
    await hero.close()
    console.log('Done')
})();

When I run the script, then the output looks like this:

Started Ulixee Cloud at localhost:1818
Now it will crash
2024-07-19T11:01:41.004Z ERROR [hero-core/connections/ConnectionToHeroClient] ConnectionToClient.HandleRequestError {
  context: {},
  sessionId: '_qlBQuMWzC2wG9hgv_noX',
  sessionName: undefined
} ProtocolError: Runtime.callFunctionOn: Cannot find context with specified id
  at new Resolvable (/home/vaclav/sandbox/ulixee/node_modules/commons/lib/Resolvable.ts:19:18)
    at createPromise (/home/vaclav/sandbox/ulixee/node_modules/commons/lib/utils.ts:147:10)
    at DevtoolsSession.send (/home/vaclav/sandbox/ulixee/agent/main/lib/DevtoolsSession.ts:82:37)
    at Frame.evaluateOnNode (/home/vaclav/sandbox/ulixee/agent/main/lib/Frame.ts:489:49)
    at Frame.getContainerOffset (/home/vaclav/sandbox/ulixee/agent/main/lib/Frame.ts:425:47)
    at async JsPath.exec (/home/vaclav/sandbox/ulixee/agent/main/lib/JsPath.ts:69:29)
    at async FrameEnvironment.execJsPath (/home/vaclav/sandbox/ulixee/node_modules/core/lib/FrameEnvironment.ts:246:12)
    at async CommandRecorder.runCommandFn (/home/vaclav/sandbox/ulixee/node_modules/core/lib/CommandRecorder.ts:90:16)
    at async CommandRunner.runFn (/home/vaclav/sandbox/ulixee/node_modules/core/lib/CommandRunner.ts:36:14)
    at async ConnectionToHeroClient.executeCommand (/home/vaclav/sandbox/ulixee/node_modules/core/connections/ConnectionToHeroClient.ts:258:12) {
  method: 'Runtime.callFunctionOn',
  remoteError: { code: -32000, message: 'Cannot find context with specified id' }
}
Unhandled Rejection: ProtocolError: Runtime.callFunctionOn: Cannot find context with specified id {
  stack: '\n' +
    '\n' +
    '  --->  await anchor.isConnected\n' +
    '\n' +
    '\n' +
    'ProtocolError: Runtime.callFunctionOn: Cannot find context with specified id\n' +
    '  at new Resolvable (/home/vaclav/sandbox/ulixee/node_modules/commons/lib/Resolvable.ts:19:18)\n' +
    '    at createPromise (/home/vaclav/sandbox/ulixee/node_modules/commons/lib/utils.ts:147:10)\n' +
    '    at DevtoolsSession.send (/home/vaclav/sandbox/ulixee/agent/main/lib/DevtoolsSession.ts:82:37)\n' +
    '    at Frame.evaluateOnNode (/home/vaclav/sandbox/ulixee/agent/main/lib/Frame.ts:489:49)\n' +
    '    at Frame.getContainerOffset (/home/vaclav/sandbox/ulixee/agent/main/lib/Frame.ts:425:47)\n' +
    '    at async JsPath.exec (/home/vaclav/sandbox/ulixee/agent/main/lib/JsPath.ts:69:29)\n' +
    '    at async FrameEnvironment.execJsPath (/home/vaclav/sandbox/ulixee/node_modules/core/lib/FrameEnvironment.ts:246:12)\n' +
    '    at async CommandRecorder.runCommandFn (/home/vaclav/sandbox/ulixee/node_modules/core/lib/CommandRecorder.ts:90:16)\n' +
    '    at async CommandRunner.runFn (/home/vaclav/sandbox/ulixee/node_modules/core/lib/CommandRunner.ts:36:14)\n' +
    '    at async ConnectionToHeroClient.executeCommand (/home/vaclav/sandbox/ulixee/node_modules/core/connections/ConnectionToHeroClient.ts:258:12)\n' +
    '------REMOTE CORE---------------------------------\n' +
    '  at Function.reviver (/home/vaclav/sandbox/ulixee/node_modules/commons/lib/TypeSerializer.ts:251:26)\n' +
    '    at JSON.parse (<anonymous>)\n' +
    '    at Function.parse (/home/vaclav/sandbox/ulixee/node_modules/commons/lib/TypeSerializer.ts:31:17)\n' +
    '    at WsTransportToCore.onMessage (/home/vaclav/sandbox/ulixee/node_modules/net/lib/WsTransportToCore.ts:105:36)\n' +
    '    at WebSocket.emit (node:events:517:28)\n' +
    '    at Receiver.receiverOnMessage (/home/vaclav/sandbox/ulixee/node_modules/ws/lib/websocket.js:1220:20)\n' +
    '    at Receiver.emit (node:events:517:28)\n' +
    '    at Receiver.dataMessage (/home/vaclav/sandbox/ulixee/node_modules/ws/lib/receiver.js:596:14)\n' +
    '    at /home/vaclav/sandbox/ulixee/node_modules/ws/lib/receiver.js:530:12\n' +
    '    at /home/vaclav/sandbox/ulixee/node_modules/ws/lib/permessage-deflate.js:309:9\n' +
    '------CONNECTION----------------------------------\n' +
    '  at new Resolvable (/home/vaclav/sandbox/ulixee/node_modules/commons/lib/Resolvable.ts:19:18)\n' +
    '    at createPromise (/home/vaclav/sandbox/ulixee/node_modules/commons/lib/utils.ts:147:10)\n' +
    '    at PendingMessages.create (/home/vaclav/sandbox/ulixee/node_modules/net/lib/PendingMessages.ts:47:44)\n' +
    '    at ConnectionToHeroCore.sendRequest (/home/vaclav/sandbox/ulixee/node_modules/net/lib/ConnectionToCore.ts:158:50)\n' +
    '    at async CoreCommandQueue.sendRequest (/home/vaclav/sandbox/ulixee/node_modules/client/lib/CoreCommandQueue.ts:317:12)\n' +
    '    at async Object.cb (/home/vaclav/sandbox/ulixee/node_modules/client/lib/CoreCommandQueue.ts:231:16)\n' +
    '    at async Queue.next (/home/vaclav/sandbox/ulixee/node_modules/commons/lib/Queue.ts:188:19)\n' +
    '------CORE COMMANDS-------------------------------\n' +
    '    at Queue.run (/home/vaclav/sandbox/ulixee/node_modules/commons/lib/Queue.ts:63:19)\n' +
    '    at CoreCommandQueue.run (/home/vaclav/sandbox/ulixee/node_modules/client/lib/CoreCommandQueue.ts:220:8)\n' +
    '    at CoreFrameEnvironment.execJsPath (/home/vaclav/sandbox/ulixee/node_modules/client/lib/CoreFrameEnvironment.ts:80:36)\n' +
    '    at execJsPath (/home/vaclav/sandbox/ulixee/node_modules/client/lib/SetupAwaitedHandler.ts:160:26)\n' +
    '    at Object.getProperty (/home/vaclav/sandbox/ulixee/node_modules/client/lib/SetupAwaitedHandler.ts:43:24)\n' +
    '    at async AwaitedHandler.getProperty (/home/vaclav/sandbox/ulixee/node_modules/files/2-finalized/awaited-dom/base/AwaitedHandler.ts:25:12)\n' +
    '    at async /home/vaclav/sandbox/ulixee/app.ts:23:5\n' +
    '\n' +
    '--------------------------------------------------\n' +
    '--------------------------------------------------\n' +
    '------_qlBQuMWzC2wG9hgv_noX-----------------------\n' +
    '--------------------------------------------------'
}

Process finished with exit code 1
@eNcacz
Copy link
Contributor Author

eNcacz commented Nov 18, 2024

I hope you’re doing well. Would you be able to find some time to look into the reported issue and work on a fix? Your assistance would be greatly appreciated.

@blakebyrnes
Copy link
Contributor

@eNcacz I'd love to find time to take a look at this but my plate is still quite full. If you have any ability to wire up a unit test like we did for the last one and see where it's breaking (it will be somewhere in agent/lib/FramesManager or Frame), that will be your best option for a quicker resolution

@kumbalek
Copy link

@blakebyrnes I looked into the problem and found the cause in the Frame in @ulixee/unblocked-agent.

It is caused by:

  public async getContainerOffset(): Promise<IPoint> {
    // This gets called on .isConnected() and this.getBoundingClientRect(); causes problem
    // if context changes and node with the frameElementNodeId no longer exists.
    // It can happen besause this.getFrameElementDevtoolsNodeId(); gets the real node id once
    // and on every subsequent call it returns the cached value.
    if (!this.parentId) return { x: 0, y: 0 };
    const parentOffset = await this.parentFrame.getContainerOffset();
    const frameElementNodeId = await this.getFrameElementDevtoolsNodeId();
    const thisOffset = await this.parentFrame.evaluateOnNode<IPoint>(
      frameElementNodeId,
      `(() => {
      const rect = this.getBoundingClientRect();
      return { x:rect.x, y:rect.y };
 })()`,
    );
    return {
      x: thisOffset.x + parentOffset.x,
      y: thisOffset.y + parentOffset.y,
    };
  }

and can be solved with change in evaluateOnNode:

public async evaluateOnNode<T>(devtoolsObjectId: string, expression: string): Promise<T> {
  if (this.closedWithError) throw this.closedWithError;
  try {
    // PROPOSED SOLUTION - Test if the node is still there, 
    // if it is not the Runtime.callFunctionOn will throw an unhandled error.
    // Other solution would be test this in getFrameElementDevtoolsNodeId() and throw error if it is not there.
    await this.parentFrame.devtoolsSession.send('DOM.getFrameOwner', { frameId: this.id }, this);

    const result = await this.devtoolsSession.send(
      'Runtime.callFunctionOn',
      {
        functionDeclaration: `function executeRemoteFn() {
      return ${expression};
    }`,
        returnByValue: true,
        objectId: devtoolsObjectId,
      },
      this,
    );
    if (result.exceptionDetails) {
      throw ConsoleMessage.exceptionToError(result.exceptionDetails);
    }

    const remote = result.result;
    if (remote.objectId) this.devtoolsSession.disposeRemoteObject(remote);
    return remote.value as T;
  } catch (err) {
    if (err instanceof CanceledPromiseError) return;
    throw err;
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants