Skip to content

Commit 79de048

Browse files
znckAkryum
authored andcommitted
feat: NativeScript support (#732)
* fix: Use window or global to store devtools hook * fix: Capture components in RouterView * fix: Capture funtional components with children instance on same vnode * test: Functional component detection * chore: Remove unnecessary console logs * refact: Move target to env * fix: Use renderContext from devtoolsMeta * fix: merge * fix: dedupe while filtering components * test: fix e2e * fix(ns): crash when changing route
1 parent b3bf00d commit 79de048

File tree

16 files changed

+261
-96
lines changed

16 files changed

+261
-96
lines changed

cypress/integration/components-tab.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { suite } from '../utils/suite'
22

3-
const baseInstanceCount = 10
3+
const baseInstanceCount = 11
44

55
suite('components tab', () => {
6+
beforeEach(() => cy.reload())
7+
68
it('should detect instances inside shadow DOM', () => {
79
cy.get('.tree > .instance:last-child').contains('Shadow')
810
})
@@ -20,6 +22,26 @@ suite('components tab', () => {
2022
cy.get('.instance').should('have.length', baseInstanceCount)
2123
})
2224

25+
it('should detect functional components', () => {
26+
cy.get('.tree > .instance .instance:nth-child(2)').within(() => {
27+
cy.get('.arrow').click().then(() => {
28+
cy.get('.instance:last-child').contains('Functional')
29+
})
30+
})
31+
})
32+
33+
it('should detect components in transition', () => {
34+
cy.get('.tree > .instance .instance:nth-child(7)').within(() => {
35+
cy.get('.arrow').click().then(() => {
36+
cy.get('.instance').eq(1).within(() => {
37+
cy.get('.arrow').click().then(() => {
38+
cy.get('.instance').contains('TestComponent')
39+
})
40+
})
41+
})
42+
})
43+
})
44+
2345
it('should select child instance', () => {
2446
cy.get('.instance .instance:nth-child(1) .self').eq(0).click()
2547
cy.get('.action-header .title').contains('Counter')
@@ -50,6 +72,8 @@ suite('components tab', () => {
5072
})
5173

5274
it('should add/remove component from app side', () => {
75+
cy.get('.instance .instance:nth-child(2) .arrow-wrapper').click()
76+
cy.get('.instance').should('have.length', baseInstanceCount + 10)
5377
cy.get('#target').iframe().then(({ get }) => {
5478
get('.add').click({ force: true })
5579
})
@@ -64,7 +88,7 @@ suite('components tab', () => {
6488
cy.get('.left .search input').clear().type('counter')
6589
cy.get('.instance').should('have.length', 1)
6690
cy.get('.left .search input').clear().type('target')
67-
cy.get('.instance').should('have.length', 15)
91+
cy.get('.instance').should('have.length', 12)
6892
cy.get('.left .search input').clear()
6993
})
7094

@@ -82,6 +106,7 @@ suite('components tab', () => {
82106
})
83107

84108
it('should display render key', () => {
109+
cy.get('.instance .instance:nth-child(2) .arrow-wrapper').click()
85110
cy.get('.instance .self .attr-title').contains('key')
86111
cy.get('.instance .self .attr-value').contains('1')
87112
})

cypress/support/commands.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Cypress.Commands.add('vueCheckInit', () => {
3333

3434
// Add iframe support until becomes part of the framework
3535
Cypress.Commands.add('iframe', { prevSubject: 'element' }, $iframe => {
36-
const get = selector => cy.wrap($iframe.contents().find(selector))
36+
const get = selector => cy.wait(500).wrap($iframe.contents().find(selector))
3737

3838
const el = $iframe[0]
3939
const iframeDoc = el.contentDocument || el.contentWindow.document

shells/dev/target/Target.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<input @keyup.enter="regex = new RegExp($event.target.value)"/>
66
<span>(Press enter to set)</span>
77
<br/>
8-
<button class="add" @mouseup="add">Add</button>
8+
<button class="add" @mouseup="add">Add 3</button>
99
<button class="remove" @mousedown="rm">Remove</button>
1010
<input v-model="localMsg">
1111
<other v-for="item in items" :key="item" :id="item"></other>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<template>
2+
<div>
3+
<div data-test-id="transition">
4+
<button v-on:click="show = !show">
5+
Toggle
6+
</button>
7+
<transition name="fade">
8+
<TestComponent v-if="show">hello</TestComponent>
9+
</transition>
10+
</div>
11+
12+
<div data-test-id="transition-list">
13+
<button v-on:click="++count">Add</button>
14+
<button v-on:click="--count">Remove</button>
15+
<transition-group name="list" tag="p">
16+
<component :is="'TestComponent'" v-for="item in count" v-bind:key="item" class="list-item">
17+
{{ item }}
18+
</component>
19+
</transition-group>
20+
</div>
21+
</div>
22+
</template>
23+
24+
<script>
25+
export default {
26+
data() {
27+
return {
28+
show: true,
29+
count: 5
30+
}
31+
},
32+
components: {
33+
TestComponent: {
34+
render(h) {
35+
return h('div', {}, this.$slots.default)
36+
}
37+
}
38+
}
39+
}
40+
</script>
41+
42+
<style scoped>
43+
.fade-enter-active, .fade-leave-active {
44+
transition: opacity .5s;
45+
}
46+
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
47+
opacity: 0;
48+
}
49+
</style>

shells/dev/target/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import NativeTypes from './NativeTypes.vue'
99
import Events from './Events.vue'
1010
import MyClass from './MyClass.js'
1111
import router from './router'
12+
import TransitionExample from './TransitionExample.vue'
1213
import Router from './router/Router.vue'
1314

1415
window.VUE_DEVTOOLS_CONFIG = {
@@ -40,6 +41,7 @@ new Vue({
4041
h(Events, { key: 'foo' }),
4142
h(NativeTypes, { key: new Date() }),
4243
h(Router, { key: [] }),
44+
h(TransitionExample),
4345
h(VuexObject),
4446
h(Init)
4547
])

shells/electron/index.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
11
require('./build/hook.js')
22

3+
const target = typeof window !== 'undefined'
4+
? window
5+
: typeof global !== 'undefined'
6+
? global
7+
: {}
8+
39
module.exports = {
4-
connect: function (host, port) {
5-
window.__VUE_DEVTOOLS_HOST__ = host
6-
window.__VUE_DEVTOOLS_PORT__ = port
10+
connect: function (host, port, { io, showToast, app } = {}) {
11+
target.__VUE_DEVTOOLS_HOST__ = host
12+
target.__VUE_DEVTOOLS_PORT__ = port
13+
if (io) target.__VUE_DEVTOOLS_SOCKET__ = io
14+
if (showToast) target.__VUE_DEVTOOLS_TOAST__ = showToast
15+
if (app) target.__VUE_ROOT_INSTANCES__ = Array.isArray(app) ? app : [app]
16+
717
require('./build/backend.js')
18+
},
19+
init: (Vue) => {
20+
const tools = target.__VUE_DEVTOOLS_GLOBAL_HOOK__
21+
22+
tools.emit('init', Vue)
823
}
924
}

shells/electron/src/backend.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,30 @@ import io from 'socket.io-client'
22
import { initBackend } from 'src/backend'
33
import Bridge from 'src/bridge'
44
import { installToast } from 'src/backend/toast'
5+
import { target } from 'src/devtools/env'
56

6-
const host = window.__VUE_DEVTOOLS_HOST__ || 'http://localhost'
7-
const port = window.__VUE_DEVTOOLS_PORT__ !== undefined ? window.__VUE_DEVTOOLS_PORT__ : 8098
7+
const host = target.__VUE_DEVTOOLS_HOST__ || 'http://localhost'
8+
const port = target.__VUE_DEVTOOLS_PORT__ !== undefined ? target.__VUE_DEVTOOLS_PORT__ : 8098
89
const fullHost = port ? host + ':' + port : host
9-
const socket = io(fullHost)
10+
const createSocket = target.__VUE_DEVTOOLS_SOCKET__ || io
11+
const socket = createSocket(fullHost)
1012

1113
const connectedMessage = () => {
12-
if (window.__VUE_DEVTOOLS_TOAST__) {
13-
window.__VUE_DEVTOOLS_TOAST__('Remote Devtools Connected', 'normal')
14+
if (target.__VUE_DEVTOOLS_TOAST__) {
15+
target.__VUE_DEVTOOLS_TOAST__('Remote Devtools Connected', 'normal')
1416
}
1517
}
1618

1719
const disconnectedMessage = () => {
18-
if (window.__VUE_DEVTOOLS_TOAST__) {
19-
window.__VUE_DEVTOOLS_TOAST__('Remote Devtools Disconnected', 'error')
20+
if (target.__VUE_DEVTOOLS_TOAST__) {
21+
target.__VUE_DEVTOOLS_TOAST__('Remote Devtools Disconnected', 'error')
2022
}
2123
}
2224

2325
socket.on('connect', () => {
2426
connectedMessage()
2527
initBackend(bridge)
28+
socket.emit('vue-devtools-init')
2629
})
2730

2831
// Global disconnect handler. Fires in two cases:
@@ -52,5 +55,4 @@ bridge.on('shutdown', () => {
5255
disconnectedMessage()
5356
})
5457

55-
installToast(window)
56-
socket.emit('vue-devtools-init')
58+
installToast(target)

shells/electron/src/hook.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
import { installHook } from 'src/backend/hook'
2+
import { target } from 'src/devtools/env'
23

3-
installHook(window)
4+
installHook(target)

src/backend/component-selector.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { highlight, unHighlight } from './highlighter'
22
import { findRelatedComponent } from './utils'
3+
import { isBrowser } from '../devtools/env'
34

45
export default class ComponentSelector {
56
constructor (bridge, instanceMap) {
@@ -16,6 +17,7 @@ export default class ComponentSelector {
1617
* Adds event listeners for mouseover and mouseup
1718
*/
1819
startSelecting () {
20+
if (!isBrowser) return
1921
document.body.addEventListener('mouseover', this.elementMouseOver, true)
2022
document.body.addEventListener('click', this.elementClicked, true)
2123
document.body.addEventListener('mouseout', this.cancelEvent, true)
@@ -29,6 +31,7 @@ export default class ComponentSelector {
2931
* Removes event listeners
3032
*/
3133
stopSelecting () {
34+
if (!isBrowser) return
3235
document.body.removeEventListener('mouseover', this.elementMouseOver, true)
3336
document.body.removeEventListener('click', this.elementClicked, true)
3437
document.body.removeEventListener('mouseout', this.cancelEvent, true)

src/backend/highlighter.js

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,31 @@
11
import { inDoc, classify, getComponentName } from '../util'
22
import { getInstanceName } from './index'
33
import SharedData from 'src/shared-data'
4-
5-
const overlay = document.createElement('div')
6-
overlay.style.backgroundColor = 'rgba(104, 182, 255, 0.35)'
7-
overlay.style.position = 'fixed'
8-
overlay.style.zIndex = '99999999999999'
9-
overlay.style.pointerEvents = 'none'
10-
overlay.style.display = 'flex'
11-
overlay.style.alignItems = 'center'
12-
overlay.style.justifyContent = 'center'
13-
overlay.style.borderRadius = '3px'
14-
const overlayContent = document.createElement('div')
15-
overlayContent.style.backgroundColor = 'rgba(104, 182, 255, 0.9)'
16-
overlayContent.style.fontFamily = 'monospace'
17-
overlayContent.style.fontSize = '11px'
18-
overlayContent.style.padding = '2px 3px'
19-
overlayContent.style.borderRadius = '3px'
20-
overlayContent.style.color = 'white'
21-
overlay.appendChild(overlayContent)
4+
import { isBrowser, target } from '../devtools/env'
5+
6+
let overlay
7+
let overlayContent
8+
9+
function init () {
10+
if (overlay || !isBrowser) return
11+
overlay = document.createElement('div')
12+
overlay.style.backgroundColor = 'rgba(104, 182, 255, 0.35)'
13+
overlay.style.position = 'fixed'
14+
overlay.style.zIndex = '99999999999999'
15+
overlay.style.pointerEvents = 'none'
16+
overlay.style.display = 'flex'
17+
overlay.style.alignItems = 'center'
18+
overlay.style.justifyContent = 'center'
19+
overlay.style.borderRadius = '3px'
20+
overlayContent = document.createElement('div')
21+
overlayContent.style.backgroundColor = 'rgba(104, 182, 255, 0.9)'
22+
overlayContent.style.fontFamily = 'monospace'
23+
overlayContent.style.fontSize = '11px'
24+
overlayContent.style.padding = '2px 3px'
25+
overlayContent.style.borderRadius = '3px'
26+
overlayContent.style.color = 'white'
27+
overlay.appendChild(overlayContent)
28+
}
2229

2330
/**
2431
* Highlight an instance.
@@ -29,6 +36,13 @@ overlay.appendChild(overlayContent)
2936
export function highlight (instance) {
3037
if (!instance) return
3138
const rect = getInstanceOrVnodeRect(instance)
39+
40+
if (!isBrowser) {
41+
// TODO: Highlight rect area.
42+
return
43+
}
44+
45+
init()
3246
if (rect) {
3347
let content = ''
3448
let name = instance.fnContext ? getComponentName(instance.fnOptions) : getInstanceName(instance)
@@ -43,20 +57,25 @@ export function highlight (instance) {
4357
*/
4458

4559
export function unHighlight () {
46-
if (overlay.parentNode) {
60+
if (overlay && overlay.parentNode) {
4761
document.body.removeChild(overlay)
4862
}
4963
}
5064

5165
/**
5266
* Get the client rect for an instance.
5367
*
54-
* @param {Vue} instance
68+
* @param {Vue|Vnode} instance
5569
* @return {Object}
5670
*/
5771

5872
export function getInstanceOrVnodeRect (instance) {
5973
const el = instance.$el || instance.elm
74+
if (!isBrowser) {
75+
// TODO: Find position from instance or a vnode (for functional components).
76+
77+
return
78+
}
6079
if (!inDoc(el)) {
6180
return
6281
}
@@ -107,16 +126,19 @@ function getFragmentRect ({ _fragmentStart, _fragmentEnd }) {
107126
}
108127
}
109128

129+
let range
110130
/**
111131
* Get the bounding rect for a text node using a Range.
112132
*
113133
* @param {Text} node
114134
* @return {Rect}
115135
*/
116-
117-
const range = document.createRange()
118136
function getTextRect (node) {
137+
if (!isBrowser) return
138+
if (!range) range = document.createRange()
139+
119140
range.selectNode(node)
141+
120142
return range.getBoundingClientRect()
121143
}
122144

@@ -127,6 +149,8 @@ function getTextRect (node) {
127149
*/
128150

129151
function showOverlay ({ width = 0, height = 0, top = 0, left = 0 }, content = '') {
152+
if (!isBrowser) return
153+
130154
overlay.style.width = ~~width + 'px'
131155
overlay.style.height = ~~height + 'px'
132156
overlay.style.top = ~~top + 'px'
@@ -142,5 +166,5 @@ function showOverlay ({ width = 0, height = 0, top = 0, left = 0 }, content = ''
142166
*/
143167

144168
function util () {
145-
return window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue.util
169+
return target.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue.util
146170
}

0 commit comments

Comments
 (0)