chromium-bidi
Advanced tools
Comparing version 0.5.1 to 0.5.2
@@ -25,3 +25,2 @@ /** | ||
import type { IBidiTransport } from './BidiTransport.js'; | ||
import { BrowsingContextStorage } from './domains/context/BrowsingContextStorage.js'; | ||
import type { OutgoingMessage } from './OutgoingMessage.js'; | ||
@@ -46,4 +45,3 @@ type BidiServerEvent = { | ||
close(): void; | ||
getBrowsingContextStorage(): BrowsingContextStorage; | ||
} | ||
export {}; |
@@ -31,2 +31,3 @@ "use strict"; | ||
#commandProcessor; | ||
#eventManager; | ||
#browsingContextStorage = new BrowsingContextStorage_js_1.BrowsingContextStorage(); | ||
@@ -52,3 +53,7 @@ #logger; | ||
this.#transport.setOnMessage(this.#handleIncomingMessage); | ||
this.#commandProcessor = new CommandProcessor_js_1.CommandProcessor(cdpConnection, browserCdpClient, new EventManager_js_1.EventManager(this), selfTargetId, this.#browsingContextStorage, new RealmStorage_js_1.RealmStorage(), options?.acceptInsecureCerts ?? false, parser, this.#logger); | ||
this.#eventManager = new EventManager_js_1.EventManager(this.#browsingContextStorage); | ||
this.#commandProcessor = new CommandProcessor_js_1.CommandProcessor(cdpConnection, browserCdpClient, this.#eventManager, selfTargetId, this.#browsingContextStorage, new RealmStorage_js_1.RealmStorage(), options?.acceptInsecureCerts ?? false, parser, this.#logger); | ||
this.#eventManager.on("event" /* EventManagerEvents.Event */, ({ message, event }) => { | ||
this.emitOutgoingMessage(message, event); | ||
}); | ||
this.#commandProcessor.on("response" /* CommandProcessorEvents.Response */, ({ message, event }) => { | ||
@@ -85,5 +90,2 @@ this.emitOutgoingMessage(message, event); | ||
} | ||
getBrowsingContextStorage() { | ||
return this.#browsingContextStorage; | ||
} | ||
async #topLevelContextsLoaded() { | ||
@@ -90,0 +92,0 @@ await Promise.all(this.#browsingContextStorage |
@@ -71,1 +71,2 @@ /** | ||
} | ||
export declare function serializeOrigin(origin: string): string; |
@@ -19,3 +19,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.BrowsingContextImpl = void 0; | ||
exports.serializeOrigin = exports.BrowsingContextImpl = void 0; | ||
const protocol_js_1 = require("../../../protocol/protocol.js"); | ||
@@ -311,17 +311,28 @@ const assert_js_1 = require("../../../utils/assert.js"); | ||
this.#cdpTarget.cdpClient.on('Runtime.executionContextCreated', (params) => { | ||
if (params.context.auxData.frameId !== this.id) { | ||
const { auxData, name, uniqueId, id } = params.context; | ||
if (!auxData || auxData.frameId !== this.id) { | ||
return; | ||
} | ||
// Only this execution contexts are supported for now. | ||
if (!['default', 'isolated'].includes(params.context.auxData.type)) { | ||
return; | ||
let origin; | ||
let sandbox; | ||
// Only these execution contexts are supported for now. | ||
switch (auxData.type) { | ||
case 'isolated': | ||
sandbox = name; | ||
// Sandbox should have the same origin as the context itself, but in CDP | ||
// it has an empty one. | ||
origin = this.#defaultRealm.origin; | ||
break; | ||
case 'default': | ||
origin = serializeOrigin(params.context.origin); | ||
break; | ||
default: | ||
return; | ||
} | ||
const realm = new Realm_js_1.Realm(this.#realmStorage, this.#browsingContextStorage, params.context.uniqueId, this.id, params.context.id, this.#getOrigin(params), | ||
const realm = new Realm_js_1.Realm(this.#realmStorage, this.#browsingContextStorage, uniqueId, this.id, id, origin, | ||
// XXX: differentiate types. | ||
'window', | ||
// Sandbox name for isolated world. | ||
params.context.auxData.type === 'isolated' | ||
? params.context.name | ||
: undefined, this.#cdpTarget.cdpClient, this.#eventManager, this.#logger); | ||
if (params.context.auxData.isDefault) { | ||
sandbox, this.#cdpTarget.cdpClient, this.#eventManager, this.#logger); | ||
if (auxData.isDefault) { | ||
this.#maybeDefaultRealm = realm; | ||
@@ -373,13 +384,2 @@ // Initialize ChannelProxy listeners for all the channels of all the | ||
} | ||
#getOrigin(params) { | ||
if (params.context.auxData.type === 'isolated') { | ||
// Sandbox should have the same origin as the context itself, but in CDP | ||
// it has an empty one. | ||
return this.#defaultRealm.origin; | ||
} | ||
// https://html.spec.whatwg.org/multipage/origin.html#ascii-serialisation-of-an-origin | ||
return ['://', ''].includes(params.context.origin) | ||
? 'null' | ||
: params.context.origin; | ||
} | ||
#documentChanged(loaderId) { | ||
@@ -720,2 +720,10 @@ // Same document navigation. | ||
exports.BrowsingContextImpl = BrowsingContextImpl; | ||
function serializeOrigin(origin) { | ||
// https://html.spec.whatwg.org/multipage/origin.html#ascii-serialisation-of-an-origin | ||
if (['://', ''].includes(origin)) { | ||
origin = 'null'; | ||
} | ||
return origin; | ||
} | ||
exports.serializeOrigin = serializeOrigin; | ||
function getImageFormatParameters(params) { | ||
@@ -742,3 +750,3 @@ const { quality, type } = params.format ?? { | ||
} | ||
throw new protocol_js_1.UnsupportedOperationException(`Image format '${type}' is not a supported format`); | ||
throw new protocol_js_1.InvalidArgumentException(`Image format '${type}' is not a supported format`); | ||
} | ||
@@ -745,0 +753,0 @@ function deserializeDOMRect(result) { |
@@ -6,2 +6,3 @@ "use strict"; | ||
const log_js_1 = require("../../../utils/log.js"); | ||
const Realm_js_1 = require("../script/Realm.js"); | ||
const BrowsingContextImpl_js_1 = require("./BrowsingContextImpl.js"); | ||
@@ -194,45 +195,71 @@ const CdpTarget_js_1 = require("./CdpTarget.js"); | ||
const targetCdpClient = this.#cdpConnection.getCdpClient(sessionId); | ||
if (!this.#isValidTarget(targetInfo)) { | ||
// DevTools or some other not supported by BiDi target. Just release | ||
// debugger and ignore them. | ||
targetCdpClient | ||
.sendCommand('Runtime.runIfWaitingForDebugger') | ||
.then(() => parentSessionCdpClient.sendCommand('Target.detachFromTarget', params)) | ||
.catch((error) => this.#logger?.(log_js_1.LogType.debugError, error)); | ||
return; | ||
} | ||
this.#logger?.(log_js_1.LogType.debugInfo, 'AttachedToTarget event received:', params); | ||
this.#setEventListeners(targetCdpClient); | ||
const maybeContext = this.#browsingContextStorage.findContext(targetInfo.targetId); | ||
const cdpTarget = CdpTarget_js_1.CdpTarget.create(targetInfo.targetId, targetCdpClient, this.#browserCdpClient, sessionId, this.#realmStorage, this.#eventManager, this.#preloadScriptStorage, this.#networkStorage, this.#acceptInsecureCerts); | ||
if (maybeContext) { | ||
// OOPiF. | ||
maybeContext.updateCdpTarget(cdpTarget); | ||
switch (targetInfo.type) { | ||
case 'page': | ||
case 'iframe': { | ||
if (targetInfo.targetId === this.#selfTargetId) { | ||
break; | ||
} | ||
this.#setEventListeners(targetCdpClient); | ||
const cdpTarget = CdpTarget_js_1.CdpTarget.create(targetInfo.targetId, targetCdpClient, this.#browserCdpClient, sessionId, this.#realmStorage, this.#eventManager, this.#preloadScriptStorage, this.#networkStorage, this.#acceptInsecureCerts); | ||
const maybeContext = this.#browsingContextStorage.findContext(targetInfo.targetId); | ||
if (maybeContext) { | ||
// OOPiF. | ||
maybeContext.updateCdpTarget(cdpTarget); | ||
} | ||
else { | ||
// New context. | ||
BrowsingContextImpl_js_1.BrowsingContextImpl.create(cdpTarget, this.#realmStorage, targetInfo.targetId, null, this.#eventManager, this.#browsingContextStorage, this.#logger); | ||
} | ||
return; | ||
} | ||
case 'worker': { | ||
this.#setEventListeners(targetCdpClient); | ||
const cdpTarget = CdpTarget_js_1.CdpTarget.create(targetInfo.targetId, targetCdpClient, this.#browserCdpClient, sessionId, this.#realmStorage, this.#eventManager, this.#preloadScriptStorage, this.#networkStorage, this.#acceptInsecureCerts); | ||
const browsingContext = parentSessionCdpClient.sessionId && | ||
this.#browsingContextStorage.findContextBySession(parentSessionCdpClient.sessionId); | ||
// If there is no browsing context, this worker is already terminated. | ||
if (!browsingContext) { | ||
break; | ||
} | ||
this.#handleWorkerTarget(cdpTarget, browsingContext.id); | ||
return; | ||
} | ||
} | ||
else { | ||
// New context. | ||
BrowsingContextImpl_js_1.BrowsingContextImpl.create(cdpTarget, this.#realmStorage, targetInfo.targetId, null, this.#eventManager, this.#browsingContextStorage, this.#logger); | ||
} | ||
// DevTools or some other not supported by BiDi target. Just release | ||
// debugger and ignore them. | ||
targetCdpClient | ||
.sendCommand('Runtime.runIfWaitingForDebugger') | ||
.then(() => parentSessionCdpClient.sendCommand('Target.detachFromTarget', params)) | ||
.catch((error) => this.#logger?.(log_js_1.LogType.debugError, error)); | ||
} | ||
#workers = new Map(); | ||
#handleWorkerTarget(cdpTarget, browsingContextId) { | ||
cdpTarget.cdpClient.on('Runtime.executionContextCreated', (params) => { | ||
const { uniqueId, id, origin } = params.context; | ||
const realm = new Realm_js_1.Realm(this.#realmStorage, this.#browsingContextStorage, uniqueId, browsingContextId, id, (0, BrowsingContextImpl_js_1.serializeOrigin)(origin), 'dedicated-worker', undefined, cdpTarget.cdpClient, this.#eventManager, this.#logger); | ||
this.#workers.set(cdpTarget.cdpSessionId, realm); | ||
}); | ||
} | ||
#handleDetachedFromTargetEvent(params) { | ||
// XXX: params.targetId is deprecated. Update this class to track using | ||
// params.sessionId instead. | ||
// https://github.com/GoogleChromeLabs/chromium-bidi/issues/60 | ||
const contextId = params.targetId; | ||
this.#browsingContextStorage.findContext(contextId)?.dispose(); | ||
this.#preloadScriptStorage | ||
.find({ targetId: contextId }) | ||
.map((preloadScript) => preloadScript.dispose(contextId)); | ||
const context = this.#browsingContextStorage.findContextBySession(params.sessionId); | ||
if (context) { | ||
context.dispose(); | ||
this.#preloadScriptStorage | ||
.find({ targetId: context.id }) | ||
.map((preloadScript) => preloadScript.dispose(context.id)); | ||
return; | ||
} | ||
const worker = this.#workers.get(params.sessionId); | ||
if (worker) { | ||
this.#realmStorage.deleteRealms({ | ||
cdpSessionId: worker.cdpClient.sessionId, | ||
}); | ||
} | ||
} | ||
#handleTargetInfoChangedEvent(params) { | ||
const contextId = params.targetInfo.targetId; | ||
this.#browsingContextStorage | ||
.findContext(contextId) | ||
?.onTargetInfoChanged(params); | ||
} | ||
#isValidTarget(target) { | ||
if (target.targetId === this.#selfTargetId) { | ||
return false; | ||
const context = this.#browsingContextStorage.findContext(params.targetInfo.targetId); | ||
if (context) { | ||
context.onTargetInfoChanged(params); | ||
} | ||
return ['page', 'iframe'].includes(target.type); | ||
} | ||
@@ -239,0 +266,0 @@ } |
@@ -38,4 +38,5 @@ /** | ||
findTopLevelContextId(id: BrowsingContext.BrowsingContext | null): BrowsingContext.BrowsingContext | null; | ||
findContextBySession(sessionId: string): BrowsingContextImpl | undefined; | ||
/** Gets the context with the given ID, if any, otherwise throws. */ | ||
getContext(id: BrowsingContext.BrowsingContext): BrowsingContextImpl; | ||
} |
@@ -65,2 +65,10 @@ "use strict"; | ||
} | ||
findContextBySession(sessionId) { | ||
for (const context of this.#contexts.values()) { | ||
if (context.cdpTarget.cdpSessionId === sessionId) { | ||
return context; | ||
} | ||
} | ||
return; | ||
} | ||
/** Gets the context with the given ID, if any, otherwise throws. */ | ||
@@ -67,0 +75,0 @@ getContext(id) { |
@@ -18,7 +18,18 @@ /** | ||
import { ChromiumBidi, type BrowsingContext } from '../../../protocol/protocol.js'; | ||
import { EventEmitter } from '../../../utils/EventEmitter.js'; | ||
import type { Result } from '../../../utils/result.js'; | ||
import type { BidiServer } from '../../BidiServer.js'; | ||
export declare class EventManager { | ||
import { OutgoingMessage } from '../../OutgoingMessage.js'; | ||
import type { BrowsingContextStorage } from '../context/BrowsingContextStorage.js'; | ||
export declare const enum EventManagerEvents { | ||
Event = "event" | ||
} | ||
type EventManagerEventsMap = { | ||
[EventManagerEvents.Event]: { | ||
message: Promise<Result<OutgoingMessage>>; | ||
event: string; | ||
}; | ||
}; | ||
export declare class EventManager extends EventEmitter<EventManagerEventsMap> { | ||
#private; | ||
constructor(bidiServer: BidiServer); | ||
constructor(browsingContextStorage: BrowsingContextStorage); | ||
registerEvent(event: ChromiumBidi.Event, contextId: BrowsingContext.BrowsingContext | null): void; | ||
@@ -29,1 +40,2 @@ registerPromiseEvent(event: Promise<Result<ChromiumBidi.Event>>, contextId: BrowsingContext.BrowsingContext | null, eventName: ChromiumBidi.EventNames): void; | ||
} | ||
export {}; |
@@ -23,2 +23,3 @@ "use strict"; | ||
const DefaultMap_js_1 = require("../../../utils/DefaultMap.js"); | ||
const EventEmitter_js_1 = require("../../../utils/EventEmitter.js"); | ||
const IdWrapper_js_1 = require("../../../utils/IdWrapper.js"); | ||
@@ -50,3 +51,3 @@ const OutgoingMessage_js_1 = require("../../OutgoingMessage.js"); | ||
const eventBufferLength = new Map([[protocol_js_1.ChromiumBidi.Log.EventNames.LogEntryAdded, 100]]); | ||
class EventManager { | ||
class EventManager extends EventEmitter_js_1.EventEmitter { | ||
/** | ||
@@ -70,6 +71,7 @@ * Maps event name to a set of contexts where this event already happened. | ||
#subscriptionManager; | ||
#bidiServer; | ||
constructor(bidiServer) { | ||
this.#bidiServer = bidiServer; | ||
this.#subscriptionManager = new SubscriptionManager_js_1.SubscriptionManager(bidiServer.getBrowsingContextStorage()); | ||
#browsingContextStorage; | ||
constructor(browsingContextStorage) { | ||
super(); | ||
this.#browsingContextStorage = browsingContextStorage; | ||
this.#subscriptionManager = new SubscriptionManager_js_1.SubscriptionManager(browsingContextStorage); | ||
} | ||
@@ -94,3 +96,6 @@ /** | ||
for (const channel of sortedChannels) { | ||
this.#bidiServer.emitOutgoingMessage(OutgoingMessage_js_1.OutgoingMessage.createFromPromise(event, channel), eventName); | ||
this.emit("event" /* EventManagerEvents.Event */, { | ||
message: OutgoingMessage_js_1.OutgoingMessage.createFromPromise(event, channel), | ||
event: eventName, | ||
}); | ||
this.#markEventSent(eventWrapper, channel, eventName); | ||
@@ -107,3 +112,3 @@ } | ||
// Assert the context is known. Throw exception otherwise. | ||
this.#bidiServer.getBrowsingContextStorage().getContext(contextId); | ||
this.#browsingContextStorage.getContext(contextId); | ||
} | ||
@@ -116,3 +121,6 @@ } | ||
// The order of the events is important. | ||
this.#bidiServer.emitOutgoingMessage(OutgoingMessage_js_1.OutgoingMessage.createFromPromise(eventWrapper.event, channel), eventName); | ||
this.emit("event" /* EventManagerEvents.Event */, { | ||
message: OutgoingMessage_js_1.OutgoingMessage.createFromPromise(eventWrapper.event, channel), | ||
event: eventName, | ||
}); | ||
this.#markEventSent(eventWrapper, channel, eventName); | ||
@@ -174,3 +182,3 @@ } | ||
// Events from deleted contexts should not be sent. | ||
this.#bidiServer.getBrowsingContextStorage().hasContext(_contextId)) | ||
this.#browsingContextStorage.hasContext(_contextId)) | ||
.map((_contextId) => this.#getBufferedEvents(eventName, _contextId, channel)) | ||
@@ -177,0 +185,0 @@ .forEach((events) => result.push(...events)); |
@@ -54,9 +54,9 @@ /** | ||
count: number; | ||
"__#87070@#x": number; | ||
"__#87070@#y": number; | ||
"__#87070@#time": number; | ||
"__#87322@#x": number; | ||
"__#87322@#y": number; | ||
"__#87322@#time": number; | ||
compare(context: any): boolean; | ||
}; | ||
"__#87070@#DOUBLE_CLICK_TIME_MS": number; | ||
"__#87070@#MAX_DOUBLE_CLICK_RADIUS": number; | ||
"__#87322@#DOUBLE_CLICK_TIME_MS": number; | ||
"__#87322@#MAX_DOUBLE_CLICK_RADIUS": number; | ||
}; | ||
@@ -63,0 +63,0 @@ setClickCount(button: number, context: InstanceType<typeof PointerSource.ClickContext>): number; |
@@ -191,3 +191,3 @@ "use strict"; | ||
networkStorage.addBlockedRequest(this.requestId, { | ||
request: params.requestId, | ||
request: params.requestId, // intercept request id | ||
phase, | ||
@@ -194,0 +194,0 @@ // TODO: Finish populating response / ResponseData. |
@@ -100,3 +100,4 @@ "use strict"; | ||
if (Object.hasOwn(bidiValue, 'backendNodeId')) { | ||
deepSerializedValue.sharedId = `${this.navigableId}${SHARED_ID_DIVIDER}${bidiValue.backendNodeId}`; | ||
deepSerializedValue.sharedId = | ||
`${this.navigableId}${SHARED_ID_DIVIDER}${bidiValue.backendNodeId}`; | ||
delete bidiValue['backendNodeId']; | ||
@@ -138,4 +139,6 @@ } | ||
get navigableId() { | ||
return (this.#browsingContextStorage.findContext(this.#browsingContextId) | ||
?.navigableId ?? 'UNKNOWN'); | ||
return ((this.browsingContextId && | ||
this.#browsingContextStorage.findContext(this.browsingContextId) | ||
?.navigableId) ?? | ||
'UNKNOWN'); | ||
} | ||
@@ -158,9 +161,18 @@ get browsingContextId() { | ||
get realmInfo() { | ||
return { | ||
realm: this.realmId, | ||
origin: this.origin, | ||
type: this.type, | ||
context: this.browsingContextId, | ||
...(this.sandbox === undefined ? {} : { sandbox: this.sandbox }), | ||
}; | ||
switch (this.type) { | ||
case 'window': | ||
return { | ||
realm: this.realmId, | ||
origin: this.origin, | ||
type: this.type, | ||
context: this.browsingContextId, | ||
...(this.sandbox === undefined ? {} : { sandbox: this.sandbox }), | ||
}; | ||
default: | ||
return { | ||
realm: this.realmId, | ||
origin: this.origin, | ||
type: this.type, | ||
}; | ||
} | ||
} | ||
@@ -167,0 +179,0 @@ async evaluate(expression, awaitPromise, resultOwnership, serializationOptions, userActivation = false) { |
@@ -58,6 +58,7 @@ "use strict"; | ||
'--disable-default-apps', | ||
'--disable-features=DialMediaRouteProvider', | ||
'--disable-features=DialMediaRouteProvider,TrackingProtection3pcd', | ||
'--disable-infobars', | ||
'--disable-notifications', | ||
'--disable-popup-blocking', | ||
'--disable-search-engine-choice-screen', | ||
'--enable-automation', | ||
@@ -64,0 +65,0 @@ '--no-default-browser-check', |
@@ -132,3 +132,3 @@ "use strict"; | ||
}); | ||
wsServer.on('request', async (request) => { | ||
wsServer.on('request', (request) => { | ||
// Session is set either by Classic or BiDi commands. | ||
@@ -135,0 +135,0 @@ let session; |
{ | ||
"name": "chromium-bidi", | ||
"version": "0.5.1", | ||
"version": "0.5.2", | ||
"description": "An implementation of the WebDriver BiDi protocol for Chromium implemented as a JavaScript layer translating between BiDi and CDP, running inside a Chrome tab.", | ||
@@ -195,13 +195,13 @@ "scripts": { | ||
"@rollup/plugin-terser": "0.4.4", | ||
"@types/argparse": "2.0.12", | ||
"@types/chai": "4.3.9", | ||
"@types/chai-as-promised": "7.1.7", | ||
"@types/debug": "4.1.10", | ||
"@types/mocha": "10.0.3", | ||
"@types/node": "20.8.10", | ||
"@types/sinon": "10.0.19", | ||
"@types/websocket": "1.0.8", | ||
"@types/ws": "8.5.8", | ||
"@typescript-eslint/eslint-plugin": "6.9.1", | ||
"@typescript-eslint/parser": "6.9.1", | ||
"@types/argparse": "2.0.14", | ||
"@types/chai": "4.3.11", | ||
"@types/chai-as-promised": "7.1.8", | ||
"@types/debug": "4.1.12", | ||
"@types/mocha": "10.0.6", | ||
"@types/node": "20.10.3", | ||
"@types/sinon": "17.0.2", | ||
"@types/websocket": "1.0.10", | ||
"@types/ws": "8.5.10", | ||
"@typescript-eslint/eslint-plugin": "6.13.2", | ||
"@typescript-eslint/parser": "6.13.2", | ||
"argparse": "2.0.1", | ||
@@ -212,5 +212,5 @@ "chai": "4.3.10", | ||
"debug": "4.3.4", | ||
"devtools-protocol": "0.0.1225305", | ||
"eslint": "8.52.0", | ||
"eslint-config-prettier": "9.0.0", | ||
"devtools-protocol": "0.0.1236148", | ||
"eslint": "8.55.0", | ||
"eslint-config-prettier": "9.1.0", | ||
"eslint-import-resolver-typescript": "3.6.1", | ||
@@ -225,10 +225,12 @@ "eslint-plugin-import": "2.29.0", | ||
"pkg-dir": "7.0.0", | ||
"prettier": "3.0.3", | ||
"prettier": "3.1.0", | ||
"rimraf": "5.0.5", | ||
"rollup": "3.29.4", | ||
"selenium-webdriver": "4.15.0", | ||
"sinon": "17.0.1", | ||
"source-map-support": "0.5.21", | ||
"terser": "5.24.0", | ||
"terser": "5.25.0", | ||
"tslib": "2.6.2", | ||
"typescript": "5.2.2", | ||
"typescript": "5.3.2", | ||
"webdriverio": "8.26.1", | ||
"websocket": "1.0.34", | ||
@@ -235,0 +237,0 @@ "wireit": "0.14.1", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
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
4264147
80935
48