metro-inspector-proxy
Advanced tools
Comparing version 0.56.3 to 0.57.0
{ | ||
"name": "metro-inspector-proxy", | ||
"version": "0.56.3", | ||
"version": "0.57.0", | ||
"description": "metro-inspector-proxy", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
@@ -20,2 +20,16 @@ /** | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
const PAGES_POLLING_INTERVAL = 1000; | ||
@@ -29,3 +43,8 @@ | ||
const FILE_PREFIX = "file://"; | ||
const REACT_NATIVE_RELOADABLE_PAGE = { | ||
id: "-1", | ||
title: "React Native Experimental (Improved Chrome Reloads)", | ||
vm: "don't use", | ||
app: "don't use" | ||
}; | ||
/** | ||
@@ -35,2 +54,3 @@ * Device class represents single device connection to Inspector Proxy. Each device | ||
*/ | ||
class Device { | ||
@@ -42,5 +62,17 @@ // ID of the device. | ||
// Stores last list of device's pages. | ||
// Maps Page ID to debugger information for the pages that are currently | ||
// debugged. | ||
// Stores information about currently connected debugger (if any). | ||
// Last known Page ID of the React Native page. | ||
// This is used by debugger connections that don't have PageID specified | ||
// (and will interact with the latest React Native page). | ||
// Whether we are in the middle of a reload in the REACT_NATIVE_RELOADABLE_PAGE. | ||
// The previous "GetPages" message, for deduplication in debug logs. | ||
constructor(id, name, app, socket) { | ||
_defineProperty(this, "_debuggerConnection", null); | ||
_defineProperty(this, "_lastReactNativePageId", null); | ||
_defineProperty(this, "_isReloading", false); | ||
_defineProperty(this, "_lastGetPagesMessage", ""); | ||
this._id = id; | ||
@@ -50,3 +82,2 @@ this._name = name; | ||
this._pages = []; | ||
this._debuggerConnections = new Map(); | ||
this._deviceSocket = socket; | ||
@@ -57,4 +88,13 @@ | ||
if (parsedMessage.event !== "getPages") { | ||
debug("<- From device: " + message); | ||
if (parsedMessage.event === "getPages") { | ||
// There's a 'getPages' message every second, so only show them if they change | ||
if (message !== this._lastGetPagesMessage) { | ||
debug( | ||
"(Debugger) (Proxy) <- (Device), getPages ping has changed: " + | ||
message | ||
); | ||
this._lastGetPagesMessage = message; | ||
} | ||
} else { | ||
debug("(Debugger) (Proxy) <- (Device): " + message); | ||
} | ||
@@ -66,7 +106,8 @@ | ||
this._deviceSocket.on("close", () => { | ||
// Device disconnected - close all debugger connections. | ||
Array.from(this._debuggerConnections.values()).forEach(_ref => { | ||
let WS = _ref.socket; | ||
return socket.close(); | ||
}); | ||
// Device disconnected - close debugger connection. | ||
if (this._debuggerConnection) { | ||
this._debuggerConnection.socket.close(); | ||
this._debuggerConnection = null; | ||
} | ||
}); | ||
@@ -82,3 +123,7 @@ | ||
getPagesList() { | ||
return this._pages; | ||
if (this._lastReactNativePageId) { | ||
return this._pages.concat(REACT_NATIVE_RELOADABLE_PAGE); | ||
} else { | ||
return this._pages; | ||
} | ||
} // Handles new debugger connection to this device: | ||
@@ -90,9 +135,15 @@ // 1. Sends connect event to device | ||
handleDebuggerConnection(socket, pageId) { | ||
// Disconnect current debugger if we already have debugger connected. | ||
if (this._debuggerConnection) { | ||
this._debuggerConnection.socket.close(); | ||
this._debuggerConnection = null; | ||
} | ||
const debuggerInfo = { | ||
socket, | ||
prependedFilePrefix: false | ||
prependedFilePrefix: false, | ||
pageId | ||
}; | ||
this._debuggerConnections.set(pageId, debuggerInfo); | ||
this._debuggerConnection = debuggerInfo; | ||
debug(`Got new debugger connection for page ${pageId} of ${this._name}`); | ||
@@ -103,3 +154,3 @@ | ||
payload: { | ||
pageId | ||
pageId: this._getPageId(pageId) | ||
} | ||
@@ -109,3 +160,3 @@ }); | ||
socket.on("message", message => { | ||
debug("<- From debugger: " + message); | ||
debug("(Debugger) -> (Proxy) (Device): " + message); | ||
const parsedMessage = JSON.parse(message); | ||
@@ -118,3 +169,3 @@ | ||
payload: { | ||
pageId, | ||
pageId: this._getPageId(pageId), | ||
wrappedEvent: JSON.stringify(parsedMessage) | ||
@@ -130,6 +181,14 @@ } | ||
payload: { | ||
pageId | ||
pageId: this._getPageId(pageId) | ||
} | ||
}); | ||
this._debuggerConnection = null; | ||
}); | ||
const sendFunc = socket.send; | ||
socket.send = function(message) { | ||
debug("(Debugger) <- (Proxy) (Device): " + message); | ||
return sendFunc.call(socket, message); | ||
}; | ||
} // Handles messages received from device: | ||
@@ -145,3 +204,17 @@ // 1. For getPages responses updates local _pages list. | ||
if (message.event === "getPages") { | ||
this._pages = message.payload; | ||
this._pages = message.payload; // Check if device have new React Native page. | ||
// There is usually no more than 2-3 pages per device so this operation | ||
// is not expensive. | ||
// TODO(hypuk): It is better for VM to send update event when new page is | ||
// created instead of manually checking this on every getPages result. | ||
for (let i = 0; i < this._pages.length; ++i) { | ||
if (this._pages[i].title.indexOf("React") >= 0) { | ||
if (this._pages[i].id != this._lastReactNativePageId) { | ||
this._newReactNativePage(this._pages[i].id); | ||
break; | ||
} | ||
} | ||
} | ||
} else if (message.event === "disconnect") { | ||
@@ -151,27 +224,31 @@ // Device sends disconnect events only when page is reloaded or | ||
const pageId = message.payload.pageId; | ||
const debuggerSocket = this._debuggerConnection | ||
? this._debuggerConnection.socket | ||
: null; | ||
const debuggerInfo = this._debuggerConnections.get(pageId); | ||
const debuggerSocket = debuggerInfo ? debuggerInfo.socket : null; | ||
if (debuggerSocket && debuggerSocket.readyState == _ws.default.OPEN) { | ||
debug(`Page ${pageId} is reloading.`); | ||
debuggerSocket.send( | ||
JSON.stringify({ | ||
method: "reload" | ||
}) | ||
); | ||
if (debuggerSocket && debuggerSocket.readyState === _ws.default.OPEN) { | ||
if ( | ||
this._debuggerConnection != null && | ||
this._debuggerConnection.pageId !== REACT_NATIVE_RELOADABLE_PAGE.id | ||
) { | ||
debug(`Page ${pageId} is reloading.`); | ||
debuggerSocket.send( | ||
JSON.stringify({ | ||
method: "reload" | ||
}) | ||
); | ||
} | ||
} | ||
} else if (message.event === "wrappedEvent") { | ||
const pageId = message.payload.pageId; | ||
const debuggerInfo = this._debuggerConnections.get(pageId); | ||
if (debuggerInfo == null) { | ||
if (this._debuggerConnection == null) { | ||
return; | ||
} | ||
} // FIXME: Is it possible that we received message for pageID that does not | ||
// correspond to current debugger connection? | ||
const debuggerSocket = debuggerInfo.socket; | ||
const debuggerSocket = this._debuggerConnection.socket; | ||
if (debuggerSocket == null) { | ||
if ( | ||
debuggerSocket == null || | ||
debuggerSocket.readyState !== _ws.default.OPEN | ||
) { | ||
// TODO(hypuk): Send error back to device? | ||
@@ -183,6 +260,8 @@ return; | ||
this._processMessageFromDevice(parsedPayload, debuggerInfo); | ||
if (this._debuggerConnection) { | ||
// Wrapping just to make flow happy :) | ||
this._processMessageFromDevice(parsedPayload, this._debuggerConnection); | ||
} | ||
const messageToSend = JSON.stringify(parsedPayload); | ||
debug("-> To debugger: " + messageToSend); | ||
debuggerSocket.send(messageToSend); | ||
@@ -195,3 +274,3 @@ } | ||
if (message.event !== "getPages") { | ||
debug("-> To device" + JSON.stringify(message)); | ||
debug("(Debugger) (Proxy) -> (Device): " + JSON.stringify(message)); | ||
} | ||
@@ -209,2 +288,61 @@ | ||
); | ||
} // We received new React Native Page ID. | ||
_newReactNativePage(pageId) { | ||
debug(`React Native page updated to ${pageId}`); | ||
if ( | ||
this._debuggerConnection == null || | ||
this._debuggerConnection.pageId !== REACT_NATIVE_RELOADABLE_PAGE.id | ||
) { | ||
// We can just remember new page ID without any further actions if no | ||
// debugger is currently attached or attached debugger is not | ||
// "Reloadable React Native" connection. | ||
this._lastReactNativePageId = pageId; | ||
return; | ||
} | ||
const oldPageId = this._lastReactNativePageId; | ||
this._lastReactNativePageId = pageId; | ||
this._isReloading = true; // We already had a debugger connected to React Native page and a | ||
// new one appeared - in this case we need to emulate execution context | ||
// detroy and resend Debugger.enable and Runtime.enable commands to new | ||
// page. | ||
if (oldPageId != null) { | ||
this._sendMessageToDevice({ | ||
event: "disconnect", | ||
payload: { | ||
pageId: oldPageId | ||
} | ||
}); | ||
} | ||
this._sendMessageToDevice({ | ||
event: "connect", | ||
payload: { | ||
pageId | ||
} | ||
}); | ||
const toSend = [ | ||
{ | ||
method: "Runtime.enable", | ||
id: 1e9 | ||
}, | ||
{ | ||
method: "Debugger.enable", | ||
id: 1e9 | ||
} | ||
]; | ||
for (const message of toSend) { | ||
this._sendMessageToDevice({ | ||
event: "wrappedEvent", | ||
payload: { | ||
pageId: this._getPageId(pageId), | ||
wrappedEvent: JSON.stringify(message) | ||
} | ||
}); | ||
} | ||
} // Allows to make changes in incoming message from device. | ||
@@ -250,3 +388,26 @@ // eslint-disable-next-line lint/no-unclear-flowtypes | ||
} | ||
if (debuggerInfo.pageId == REACT_NATIVE_RELOADABLE_PAGE.id) { | ||
// Chrome won't use the source map unless it appears to be new. | ||
payload.params.sourceMapURL += | ||
"&cachePrevention=" + this._getPageId(debuggerInfo.pageId); | ||
payload.params.url += | ||
"&cachePrevention=" + this._getPageId(debuggerInfo.pageId); | ||
} | ||
} | ||
if ( | ||
payload.method === "Runtime.executionContextCreated" && | ||
this._isReloading | ||
) { | ||
// The new context is ready. First notify Chrome that we've reloaded so | ||
// it'll resend its breakpoints. If we do this earlier, we may not be | ||
// ready to receive them. | ||
debuggerInfo.socket.send( | ||
JSON.stringify({ | ||
method: "Runtime.executionContextsCleared" | ||
}) | ||
); | ||
this._isReloading = false; | ||
} | ||
} // Allows to make changes in incoming messages from debugger. | ||
@@ -286,4 +447,15 @@ // eslint-disable-next-line lint/no-unclear-flowtypes | ||
} | ||
_getPageId(pageId) { | ||
if ( | ||
pageId === REACT_NATIVE_RELOADABLE_PAGE.id && | ||
this._lastReactNativePageId != null | ||
) { | ||
return this._lastReactNativePageId; | ||
} else { | ||
return pageId; | ||
} | ||
} | ||
} | ||
module.exports = Device; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
49472
709