// Copyright 2018 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. InspectorTest.log('Test for Runtime.addBinding.'); InspectorTest.runAsyncTestSuite([ async function testBasic() { const {contextGroup, sessions: [session1, session2]} = setupSessions(2); InspectorTest.log('\nAdd binding inside session1..'); session1.Protocol.Runtime.addBinding({name: 'send'}); InspectorTest.log('Call binding..'); await session1.Protocol.Runtime.evaluate({expression: `send('payload')`}); InspectorTest.log('\nAdd binding inside session2..'); session2.Protocol.Runtime.addBinding({name: 'send'}); InspectorTest.log('Call binding..'); await session2.Protocol.Runtime.evaluate({expression: `send('payload')`}); InspectorTest.log('\nDisable agent inside session1..'); session1.Protocol.Runtime.disable(); InspectorTest.log('Call binding..'); await session2.Protocol.Runtime.evaluate({expression: `send('payload')`}); InspectorTest.log('\nDisable agent inside session2..'); session2.Protocol.Runtime.disable(); InspectorTest.log('Call binding..'); await session2.Protocol.Runtime.evaluate({expression: `send('payload')`}); InspectorTest.log('\nEnable agent inside session1..'); session1.Protocol.Runtime.enable(); InspectorTest.log('Call binding..'); await session2.Protocol.Runtime.evaluate({expression: `send('payload')`}); }, async function testReconnect() { const {contextGroup, sessions: [session]} = setupSessions(1); InspectorTest.log('\nAdd binding inside session..'); await session.Protocol.Runtime.addBinding({name: 'send'}); InspectorTest.log('Reconnect..'); session.reconnect(); await session.Protocol.Runtime.evaluate({expression: `send('payload')`}); }, async function testBindingOverrides() { const {contextGroup, sessions: [session]} = setupSessions(1); InspectorTest.log('\nAdd send function on global object..'); session.Protocol.Runtime.evaluate({expression: 'send = () => 42'}); InspectorTest.log('Add binding inside session..'); session.Protocol.Runtime.addBinding({name: 'send'}); InspectorTest.log('Call binding..'); await session.Protocol.Runtime.evaluate({expression: `send('payload')`}); }, async function testRemoveBinding() { const {contextGroup, sessions: [session]} = setupSessions(1); InspectorTest.log('\nAdd binding inside session..'); session.Protocol.Runtime.addBinding({name: 'send'}); InspectorTest.log('Call binding..'); await session.Protocol.Runtime.evaluate({expression: `send('payload')`}); InspectorTest.log('Remove binding inside session..'); session.Protocol.Runtime.removeBinding({name: 'send'}); InspectorTest.log('Call binding..'); await session.Protocol.Runtime.evaluate({expression: `send('payload')`}); }, async function testAddBindingToContextById() { const {contextGroup, sessions: [session]} = setupSessions(1); const contextId1 = (await session.Protocol.Runtime.onceExecutionContextCreated()).params.context.id; contextGroup.createContext(); const contextId2 = (await session.Protocol.Runtime.onceExecutionContextCreated()).params.context.id; await session.Protocol.Runtime.addBinding({name: 'frobnicate', executionContextId: contextId2}); const expression = `frobnicate('message')`; InspectorTest.log('Call binding in default context (binding should NOT be exposed)'); await session.Protocol.Runtime.evaluate({expression}); InspectorTest.log('Call binding in target context (binding should be exposed)'); await session.Protocol.Runtime.evaluate({expression, contextId: contextId2}); InspectorTest.log('Call binding in newly created context (binding should NOT be exposed)'); contextGroup.createContext(); const contextId3 = (await session.Protocol.Runtime.onceExecutionContextCreated()).params.context.id; await session.Protocol.Runtime.evaluate({expression, contextId: contextId3}); }, async function testAddBindingToMultipleContextsById() { const {contextGroup, sessions: [session]} = setupSessions(1); const contextId1 = (await session.Protocol.Runtime.onceExecutionContextCreated()).params.context.id; contextGroup.createContext(); const contextId2 = (await session.Protocol.Runtime.onceExecutionContextCreated()).params.context.id; await session.Protocol.Runtime.addBinding({name: 'frobnicate', executionContextId: contextId1}); await session.Protocol.Runtime.addBinding({name: 'frobnicate', executionContextId: contextId2}); const expression = `frobnicate('message')`; InspectorTest.log('Call binding in default context (binding should be exposed)'); await session.Protocol.Runtime.evaluate({expression}); InspectorTest.log('Call binding in target context (binding should be exposed)'); await session.Protocol.Runtime.evaluate({expression, contextId: contextId2}); }, async function testAddBindingToMultipleContextsInDifferentContextGroups() { const sessions1 = setupSessions(1, 'group1/'); const session1 = sessions1.sessions[0]; const contextId1 = (await session1.Protocol.Runtime.onceExecutionContextCreated()).params.context.id; const sessions2 = setupSessions(1, 'group2/'); const session2 = sessions2.sessions[0]; const contextId2 = (await session2.Protocol.Runtime.onceExecutionContextCreated()).params.context.id; await session1.Protocol.Runtime.addBinding({name: 'frobnicate', executionContextId: contextId1}); await session2.Protocol.Runtime.addBinding({name: 'frobnicate', executionContextId: contextId2}); const expression = `frobnicate('message')`; InspectorTest.log('Call binding in default context (binding should be exposed)'); await session1.Protocol.Runtime.evaluate({expression, contextId: contextId1}); InspectorTest.log('Call binding in target context (binding should be exposed)'); await session2.Protocol.Runtime.evaluate({expression, contextId: contextId2}); }, async function testAddBindingToContextByName() { const {contextGroup, sessions: [session]} = setupSessions(1); const defaultContext = (await session.Protocol.Runtime.onceExecutionContextCreated()).params.context.id; contextGroup.createContext("foo"); const contextFoo = (await session.Protocol.Runtime.onceExecutionContextCreated()).params.context.id; contextGroup.createContext("bar"); const contextBar = (await session.Protocol.Runtime.onceExecutionContextCreated()).params.context.id; await session.Protocol.Runtime.addBinding({name: 'frobnicate', executionContextName: 'foo'}); const expression = `frobnicate('message')`; InspectorTest.log('Call binding in default context (binding should NOT be exposed)'); await session.Protocol.Runtime.evaluate({expression}); InspectorTest.log('Call binding in Foo (binding should be exposed)'); await session.Protocol.Runtime.evaluate({expression, contextId: contextFoo}); InspectorTest.log('Call binding in Bar (binding should NOT be exposed)'); await session.Protocol.Runtime.evaluate({expression, contextId: contextBar}); contextGroup.createContext("foo"); const contextFoo2 = (await session.Protocol.Runtime.onceExecutionContextCreated()).params.context.id; InspectorTest.log('Call binding in newly-created Foo (binding should be exposed)'); await session.Protocol.Runtime.evaluate({expression, contextId: contextFoo2}); contextGroup.createContext("bazz"); const contextBazz = (await session.Protocol.Runtime.onceExecutionContextCreated()).params.context.id; InspectorTest.log('Call binding in newly-created Bazz (binding should NOT be exposed)'); await session.Protocol.Runtime.evaluate({expression, contextId: contextBazz}); }, async function testErrors() { const {contextGroup, sessions: [session]} = setupSessions(1); let err = await session.Protocol.Runtime.addBinding({name: 'frobnicate', executionContextName: ''}); InspectorTest.logMessage(err); err = await session.Protocol.Runtime.addBinding({name: 'frobnicate', executionContextName: 'foo', executionContextId: 1}); InspectorTest.logMessage(err); err = await session.Protocol.Runtime.addBinding({name: 'frobnicate', executionContextId: 2128506}); InspectorTest.logMessage(err); } ]); function setupSessions(num, prefix = '') { const contextGroup = new InspectorTest.ContextGroup(); const sessions = []; for (let i = 0; i < num; ++i) { const session = contextGroup.connect(); sessions.push(session); session.Protocol.Runtime.enable(); session.Protocol.Runtime.onBindingCalled(msg => { InspectorTest.log(`binding called in ${prefix}session${i + 1}`); InspectorTest.logMessage(msg); }); } return {contextGroup, sessions}; }