diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index 70c25460b5..155b64778b 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -32,6 +32,7 @@ import { is_reserved_keyword } from './utils/reserved_keywords'; import { apply_preprocessor_sourcemap } from '../utils/mapped_code'; import Element from './nodes/Element'; import { DecodedSourceMap, RawSourceMap } from '@ampproject/remapping/dist/types/types'; +import { clone } from '../utils/clone'; interface ComponentOptions { namespace?: string; @@ -116,12 +117,12 @@ export default class Component { // the instance JS gets mutated, so we park // a copy here for later. TODO this feels gross - this.original_ast = { + this.original_ast = clone({ html: ast.html, css: ast.css, - instance: ast.instance && JSON.parse(JSON.stringify(ast.instance)), + instance: ast.instance, module: ast.module - }; + }); this.file = compile_options.filename && diff --git a/src/compiler/compile/nodes/Binding.ts b/src/compiler/compile/nodes/Binding.ts index 3a9aa943e9..8fcc70ded9 100644 --- a/src/compiler/compile/nodes/Binding.ts +++ b/src/compiler/compile/nodes/Binding.ts @@ -9,6 +9,7 @@ import { TemplateNode } from '../../interfaces'; import Element from './Element'; import InlineComponent from './InlineComponent'; import Window from './Window'; +import { clone } from '../../utils/clone'; // TODO this should live in a specific binding const read_only_media_attributes = new Set([ @@ -42,7 +43,7 @@ export default class Binding extends Node { this.name = info.name; this.expression = new Expression(component, this, scope, info.expression); - this.raw_expression = JSON.parse(JSON.stringify(info.expression)); + this.raw_expression = clone(info.expression); const { name } = get_object(this.expression.node); diff --git a/src/compiler/compile/nodes/shared/Context.ts b/src/compiler/compile/nodes/shared/Context.ts index c6ad2c2893..dbcdada587 100644 --- a/src/compiler/compile/nodes/shared/Context.ts +++ b/src/compiler/compile/nodes/shared/Context.ts @@ -2,6 +2,7 @@ import { x } from 'code-red'; import { Node, Identifier, Expression } from 'estree'; import { walk } from 'estree-walker'; import is_reference from 'is-reference'; +import { clone } from '../../../utils/clone'; export interface Context { key: Identifier; @@ -81,7 +82,7 @@ function update_reference(contexts: Context[], n: number, expression: Expression } // NOTE: avoid unnecessary deep clone? - expression = JSON.parse(JSON.stringify(expression)) as Expression; + expression = clone(expression) as Expression; walk(expression, { enter(node, parent: Node) { if (is_reference(node, parent)) { diff --git a/src/compiler/compile/nodes/shared/Expression.ts b/src/compiler/compile/nodes/shared/Expression.ts index caece14f00..cca81b6372 100644 --- a/src/compiler/compile/nodes/shared/Expression.ts +++ b/src/compiler/compile/nodes/shared/Expression.ts @@ -16,6 +16,7 @@ import { is_reserved_keyword } from '../../utils/reserved_keywords'; import replace_object from '../../utils/replace_object'; import is_contextual from './is_contextual'; import EachBlock from '../EachBlock'; +import { clone } from '../../../utils/clone'; type Owner = INode; @@ -195,7 +196,7 @@ export default class Expression { const node = walk(this.node, { enter(node: any, parent: any) { if (node.type === 'Property' && node.shorthand) { - node.value = JSON.parse(JSON.stringify(node.value)); + node.value = clone(node.value); node.shorthand = false; }