Skip to content

Commit

Permalink
Merge branch 'dev' of github.com:vuejs/vue into new-type
Browse files Browse the repository at this point in the history
  • Loading branch information
HerringtonDarkholme committed Aug 29, 2017
2 parents 67eab9c + 5091e2c commit 97a401e
Show file tree
Hide file tree
Showing 9 changed files with 836 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/platforms/web/server/modules/attrs.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function renderAttr (key: string, value: string): string {
} else if (isEnumeratedAttr(key)) {
return ` ${key}="${isFalsyAttrValue(value) || value === 'false' ? 'false' : 'true'}"`
} else if (!isFalsyAttrValue(value)) {
return ` ${key}="${typeof value === 'string' ? cachedEscape(value) : value}"`
return ` ${key}="${cachedEscape(String(value))}"`
}
return ''
}
15 changes: 11 additions & 4 deletions src/platforms/weex/entry-framework.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ export function createInstance (
// It will declare some instance variables like `Vue`, HTML5 Timer APIs etc.
const instanceVars = Object.assign({
Vue,
weex: weexInstanceVar,
// deprecated
__weex_require_module__: weexInstanceVar.requireModule // eslint-disable-line
weex: weexInstanceVar
}, timerAPIs, env.services)

appCode = `(function(global){ \n${appCode}\n })(Object.create(this))`

if (!callFunctionNative(instanceVars, appCode)) {
// If failed to compile functionBody on native side,
// fallback to 'callFunction()'.
Expand All @@ -104,6 +104,8 @@ export function createInstance (

// Send `createFinish` signal to native.
instance.document.taskCenter.send('dom', { action: 'createFinish' }, [])

return instance
}

/**
Expand Down Expand Up @@ -289,10 +291,15 @@ function createVueModuleInstance (instanceId, moduleGetter) {

// patch reserved tag detection to account for dynamically registered
// components
const weexRegex = /^weex:/i
const isReservedTag = Vue.config.isReservedTag || (() => false)
const isRuntimeComponent = Vue.config.isRuntimeComponent || (() => false)
Vue.config.isReservedTag = name => {
return components[name] || isReservedTag(name)
return (!isRuntimeComponent(name) && components[name]) ||
isReservedTag(name) ||
weexRegex.test(name)
}
Vue.config.parsePlatformTagName = name => name.replace(weexRegex, '')

// expose weex-specific info
Vue.prototype.$instanceId = instanceId
Expand Down
2 changes: 2 additions & 0 deletions src/platforms/weex/runtime/components/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import Richtext from './richtext'
import Transition from './transition'
import TransitionGroup from './transition-group'

export default {
Richtext,
Transition,
TransitionGroup
}
95 changes: 95 additions & 0 deletions src/platforms/weex/runtime/components/richtext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
function getVNodeType (vnode) {
if (!vnode.tag) {
return ''
}
return vnode.tag.replace(/vue\-component\-(\d+\-)?/, '')
}

function isSimpleSpan (vnode) {
return vnode.children && vnode.children.length === 1 && !vnode.children[0].tag
}

const cssLengthRE = /^([+-]?[0-9]+(\.[0-9]+)?)(px|em|ex|%|in|cm|mm|pt|pc)$/i
function trimCSSUnit (prop) {
const res = String(prop).match(cssLengthRE)
if (res) {
return Number(res[1])
}
return prop
}

function parseStyle (vnode) {
if (!vnode || !vnode.data) {
return
}

const { staticStyle, staticClass } = vnode.data
if (vnode.data.style || vnode.data.class || staticStyle || staticClass) {
const styles = Object.assign({}, staticStyle, vnode.data.style)

const cssMap = vnode.context.$options.style || {}
const classList = [].concat(staticClass, vnode.data.class)
classList.forEach(name => {
if (name && cssMap[name]) {
Object.assign(styles, cssMap[name])
}
})

for (const key in styles) {
styles[key] = trimCSSUnit(styles[key])
}
return styles
}
}

function convertVNodeChildren (children) {
if (!children.length) {
return
}

return children.map(vnode => {
const type = getVNodeType(vnode)
const props = { type }

// convert raw text node
if (!type) {
props.type = 'span'
props.attr = {
value: (vnode.text || '').trim()
}
} else {
props.style = parseStyle(vnode)
if (vnode.data) {
props.attr = vnode.data.attrs
if (vnode.data.on) {
props.events = vnode.data.on
}
}

if (type === 'span' && isSimpleSpan(vnode)) {
props.attr = props.attr || {}
props.attr.value = vnode.children[0].text.trim()
return props
}
}

if (vnode.children && vnode.children.length) {
props.children = convertVNodeChildren(vnode.children)
}

return props
})
}

export default {
name: 'richtext',
// abstract: true,
render (h) {
return h('weex:richtext', {
on: this._events,
attrs: {
value: convertVNodeChildren(this.$options._renderChildren || [])
}
})
}
}
2 changes: 2 additions & 0 deletions src/platforms/weex/runtime/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import {
query,
mustUseProp,
isReservedTag,
isRuntimeComponent,
isUnknownElement
} from 'weex/util/index'

// install platform specific utils
Vue.config.mustUseProp = mustUseProp
Vue.config.isReservedTag = isReservedTag
Vue.config.isRuntimeComponent = isRuntimeComponent
Vue.config.isUnknownElement = isUnknownElement

// install platform runtime directives and components
Expand Down
9 changes: 7 additions & 2 deletions src/platforms/weex/util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { makeMap } from 'shared/util'

export const isReservedTag = makeMap(
'template,script,style,element,content,slot,link,meta,svg,view,' +
'a,div,img,image,text,span,richtext,input,switch,textarea,spinner,select,' +
'slider,slider-neighbor,indicator,trisition,trisition-group,canvas,' +
'a,div,img,image,text,span,input,switch,textarea,spinner,select,' +
'slider,slider-neighbor,indicator,canvas,' +
'list,cell,header,loading,loading-indicator,refresh,scrollable,scroller,' +
'video,web,embed,tabbar,tabheader,datepicker,timepicker,marquee,countdown',
true
Expand All @@ -19,6 +19,11 @@ export const canBeLeftOpenTag = makeMap(
true
)

export const isRuntimeComponent = makeMap(
'richtext,trisition,trisition-group',
true
)

export const isUnaryTag = makeMap(
'embed,img,image,input,link,meta',
true
Expand Down
13 changes: 13 additions & 0 deletions test/ssr/ssr-string.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,19 @@ describe('SSR: renderToString', () => {
})
})

it('should prevent script xss with v-bind object syntax + array value', done => {
renderVmWithOptions({
data: {
test: ['"><script>alert(1)</script><!--"']
},
template: `<div v-bind="{ test }"></div>`
}, res => {
console.log(res)
expect(res).not.toContain(`<script>alert(1)</script>`)
done()
})
})

it('v-if', done => {
renderVmWithOptions({
template: `
Expand Down
Loading

0 comments on commit 97a401e

Please sign in to comment.