perf(compiler): should only perform assertions during tests

Compiler assertions are made to ensure implementation correctness,
but they have performance costs that should not affect users
during development.
This commit is contained in:
Evan You 2019-11-15 17:29:08 -05:00
parent 51d57b4566
commit 353b06df77
4 changed files with 32 additions and 25 deletions

View File

@ -141,7 +141,7 @@ function parseChildren(
const nodes: TemplateChildNode[] = []
while (!isEnd(context, mode, ancestors)) {
__DEV__ && assert(context.source.length > 0)
__TEST__ && assert(context.source.length > 0)
const s = context.source
let node: TemplateChildNode | TemplateChildNode[] | undefined = undefined
@ -286,16 +286,16 @@ function parseCDATA(
context: ParserContext,
ancestors: ElementNode[]
): TemplateChildNode[] {
__DEV__ &&
__TEST__ &&
assert(last(ancestors) == null || last(ancestors)!.ns !== Namespaces.HTML)
__DEV__ && assert(startsWith(context.source, '<![CDATA['))
__TEST__ && assert(startsWith(context.source, '<![CDATA['))
advanceBy(context, 9)
const nodes = parseChildren(context, TextModes.CDATA, ancestors)
if (context.source.length === 0) {
emitError(context, ErrorCodes.EOF_IN_CDATA)
} else {
__DEV__ && assert(startsWith(context.source, ']]>'))
__TEST__ && assert(startsWith(context.source, ']]>'))
advanceBy(context, 3)
}
@ -303,7 +303,7 @@ function parseCDATA(
}
function parseComment(context: ParserContext): CommentNode {
__DEV__ && assert(startsWith(context.source, '<!--'))
__TEST__ && assert(startsWith(context.source, '<!--'))
const start = getCursor(context)
let content: string
@ -345,7 +345,7 @@ function parseComment(context: ParserContext): CommentNode {
}
function parseBogusComment(context: ParserContext): CommentNode | undefined {
__DEV__ && assert(/^<(?:[\!\?]|\/[^a-z>])/i.test(context.source))
__TEST__ && assert(/^<(?:[\!\?]|\/[^a-z>])/i.test(context.source))
const start = getCursor(context)
const contentStart = context.source[1] === '?' ? 1 : 2
@ -371,7 +371,7 @@ function parseElement(
context: ParserContext,
ancestors: ElementNode[]
): ElementNode | undefined {
__DEV__ && assert(/^<[a-z]/i.test(context.source))
__TEST__ && assert(/^<[a-z]/i.test(context.source))
// Start tag.
const wasInPre = context.inPre
@ -425,8 +425,8 @@ function parseTag(
type: TagType,
parent: ElementNode | undefined
): ElementNode {
__DEV__ && assert(/^<\/?[a-z]/i.test(context.source))
__DEV__ &&
__TEST__ && assert(/^<\/?[a-z]/i.test(context.source))
__TEST__ &&
assert(
type === (startsWith(context.source, '</') ? TagType.End : TagType.Start)
)
@ -538,7 +538,7 @@ function parseAttribute(
context: ParserContext,
nameSet: Set<string>
): AttributeNode | DirectiveNode {
__DEV__ && assert(/^[^\t\r\n\f />]/.test(context.source))
__TEST__ && assert(/^[^\t\r\n\f />]/.test(context.source))
// Name.
const start = getCursor(context)
@ -725,7 +725,7 @@ function parseInterpolation(
mode: TextModes
): InterpolationNode | undefined {
const [open, close] = context.options.delimiters
__DEV__ && assert(startsWith(context.source, open))
__TEST__ && assert(startsWith(context.source, open))
const closeIndex = context.source.indexOf(close, open.length)
if (closeIndex === -1) {
@ -765,7 +765,7 @@ function parseInterpolation(
}
function parseText(context: ParserContext, mode: TextModes): TextNode {
__DEV__ && assert(context.source.length > 0)
__TEST__ && assert(context.source.length > 0)
const [open] = context.options.delimiters
// TODO could probably use some perf optimization
@ -777,7 +777,7 @@ function parseText(context: ParserContext, mode: TextModes): TextNode {
context.source.length
].filter(n => n !== -1)
)
__DEV__ && assert(endIndex > 0)
__TEST__ && assert(endIndex > 0)
const start = getCursor(context)
const content = parseTextData(context, endIndex, mode)
@ -951,7 +951,7 @@ function startsWith(source: string, searchString: string): boolean {
function advanceBy(context: ParserContext, numberOfCharacters: number): void {
const { source } = context
__DEV__ && assert(numberOfCharacters <= source.length)
__TEST__ && assert(numberOfCharacters <= source.length)
advancePositionWithMutation(context, source, numberOfCharacters)
context.source = source.slice(numberOfCharacters)
}

View File

@ -51,7 +51,7 @@ export const transformElement: NodeTransform = (node, context) => {
}
// perform the work on exit, after all child expressions have been
// processed and merged.
return () => {
return function postTransformElement() {
const { tag, tagType, props } = node
const isPortal = tag === 'portal' || tag === 'Portal'
const isSuspense = tag === 'suspense' || tag === 'Suspense'
@ -113,7 +113,7 @@ export const transformElement: NodeTransform = (node, context) => {
node,
context,
// skip reserved "is" prop <component is>
node.props.filter(p => p !== isProp)
isProp ? node.props.filter(p => p !== isProp) : node.props
)
patchFlag = propsBuildResult.patchFlag
dynamicPropNames = propsBuildResult.dynamicPropNames
@ -177,9 +177,7 @@ export const transformElement: NodeTransform = (node, context) => {
args.push(patchFlag + '')
}
if (dynamicPropNames && dynamicPropNames.length) {
args.push(
`[${dynamicPropNames.map(n => JSON.stringify(n)).join(`, `)}]`
)
args.push(stringifyDynamicPropNames(dynamicPropNames))
}
}
@ -204,6 +202,15 @@ export const transformElement: NodeTransform = (node, context) => {
}
}
function stringifyDynamicPropNames(props: string[]): string {
let propsNamesString = `[`
for (let i = 0, l = props.length; i < l; i++) {
propsNamesString += JSON.stringify(props[i])
if (i < l - 1) propsNamesString += ', '
}
return propsNamesString + `]`
}
export type PropsExpression = ObjectExpression | CallExpression | ExpressionNode
export function buildProps(
@ -410,7 +417,7 @@ export function buildProps(
// - onXXX handlers / style: merge into array
// - class: merge into single expression with concatenation
function dedupeProperties(properties: Property[]): Property[] {
const knownProps: Record<string, Property> = {}
const knownProps: Map<string, Property> = new Map()
const deduped: Property[] = []
for (let i = 0; i < properties.length; i++) {
const prop = properties[i]
@ -420,7 +427,7 @@ function dedupeProperties(properties: Property[]): Property[] {
continue
}
const name = prop.key.content
const existing = knownProps[name]
const existing = knownProps.get(name)
if (existing) {
if (
name === 'style' ||
@ -432,7 +439,7 @@ function dedupeProperties(properties: Property[]): Property[] {
}
// unexpected duplicate, should have emitted error during parse
} else {
knownProps[name] = prop
knownProps.set(name, prop)
deduped.push(prop)
}
}

View File

@ -208,7 +208,7 @@ export function buildSlots(
// remove node
children.splice(i, 1)
i--
__DEV__ && assert(dynamicSlots.length > 0)
__TEST__ && assert(dynamicSlots.length > 0)
// attach this slot to previous conditional
let conditional = dynamicSlots[
dynamicSlots.length - 1

View File

@ -77,7 +77,7 @@ export function getInnerRange(
offset: number,
length?: number
): SourceLocation {
__DEV__ && assert(offset <= loc.source.length)
__TEST__ && assert(offset <= loc.source.length)
const source = loc.source.substr(offset, length)
const newLoc: SourceLocation = {
source,
@ -86,7 +86,7 @@ export function getInnerRange(
}
if (length != null) {
__DEV__ && assert(offset + length <= loc.source.length)
__TEST__ && assert(offset + length <= loc.source.length)
newLoc.end = advancePositionWithClone(
loc.start,
loc.source,