dist/ember-template-compiler.js in ember-source-1.10.0.beta.3 vs dist/ember-template-compiler.js in ember-source-1.10.0.beta.4
- old
+ new
@@ -3,11 +3,11 @@
* @copyright Copyright 2011-2014 Tilde Inc. and contributors
* Portions Copyright 2006-2011 Strobe Inc.
* Portions Copyright 2008-2011 Apple Inc. All rights reserved.
* @license Licensed under MIT license
* See https://raw.github.com/emberjs/ember.js/master/LICENSE
- * @version 1.10.0-beta.3
+ * @version 1.10.0-beta.4
*/
(function() {
var define, requireModule, require, requirejs, Ember;
@@ -112,11 +112,11 @@
The core Runtime framework is based on the jQuery API with a number of
performance optimizations.
@class Ember
@static
- @version 1.10.0-beta.3
+ @version 1.10.0-beta.4
*/
if ('undefined' === typeof Ember) {
// Create core object. Make it act like an instance of Ember.Namespace so that
// objects assigned to it are given a sane string representation.
@@ -139,14 +139,14 @@
/**
@property VERSION
@type String
- @default '1.10.0-beta.3'
+ @default '1.10.0-beta.4'
@static
*/
- Ember.VERSION = '1.10.0-beta.3';
+ Ember.VERSION = '1.10.0-beta.4';
/**
Standard environmental variables. You can define these in a global `EmberENV`
variable before loading Ember to control various configuration settings.
@@ -399,10 +399,15 @@
var walker = new pluginContext.syntax.Walker();
var b = pluginContext.syntax.builders;
walker.visit(ast, function(node) {
if (pluginContext.validate(node)) {
+
+ if (node.program && node.program.blockParams.length) {
+ throw new Error('You cannot use keyword (`{{each foo in bar}}`) and block params (`{{each bar as |foo|}}`) at the same time.');
+ }
+
var removedParams = node.sexpr.params.splice(0, 2);
var keyword = removedParams[0].original;
// TODO: This may not be necessary.
if (!node.sexpr.hash) {
@@ -470,10 +475,15 @@
var pluginContext = this;
var walker = new pluginContext.syntax.Walker();
walker.visit(ast, function(node) {
if (pluginContext.validate(node)) {
+
+ if (node.program && node.program.blockParams.length) {
+ throw new Error('You cannot use keyword (`{{with foo as bar}}`) and block params (`{{with foo as |bar|}}`) at the same time.');
+ }
+
var removedParams = node.sexpr.params.splice(1, 2);
var keyword = removedParams[1].original;
node.program.blockParams = [ keyword ];
}
});
@@ -737,13 +747,17 @@
FragmentJavaScriptCompiler.prototype.returnNode = function() {
var el = 'el'+this.depth;
this.source.push(this.indent+' return '+el+';\n');
};
- FragmentJavaScriptCompiler.prototype.setAttribute = function(name, value) {
+ FragmentJavaScriptCompiler.prototype.setAttribute = function(name, value, namespace) {
var el = 'el'+this.depth;
- this.source.push(this.indent+' dom.setProperty('+el+','+string(name)+','+string(value)+');\n');
+ if (namespace) {
+ this.source.push(this.indent+' dom.setAttributeNS('+el+','+string(namespace)+','+string(name)+','+string(value)+');\n');
+ } else {
+ this.source.push(this.indent+' dom.setAttribute('+el+','+string(name)+','+string(value)+');\n');
+ }
};
FragmentJavaScriptCompiler.prototype.appendChild = function() {
if (this.depth === this.getCurrentNamespaceFrame().depth) {
this.popNamespaceFrame();
@@ -777,10 +791,11 @@
["./template-visitor","./utils","../htmlbars-util/array-utils","exports"],
function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
"use strict";
var TemplateVisitor = __dependency1__["default"];
var processOpcodes = __dependency2__.processOpcodes;
+ var getNamespace = __dependency2__.getNamespace;
var forEach = __dependency3__.forEach;
function FragmentOpcodeCompiler() {
this.opcodes = [];
}
@@ -836,11 +851,14 @@
FragmentOpcodeCompiler.prototype.block = function () {};
FragmentOpcodeCompiler.prototype.attribute = function(attr) {
if (attr.value.type === 'TextNode') {
- this.opcode('setAttribute', [attr.name, attr.value.chars]);
+
+ var namespace = getNamespace(attr.name) || null;
+
+ this.opcode('setAttribute', [attr.name, attr.value.chars, namespace]);
}
};
FragmentOpcodeCompiler.prototype.setNamespace = function(namespace) {
this.opcode('setNamespace', [namespace]);
@@ -1056,22 +1074,22 @@
(isRoot ? ",contextualElement)" : ")");
this.morphs.push(['morph' + morphNum, morph]);
};
- prototype.createAttrMorph = function(attrMorphNum, elementNum, name, escaped) {
+ prototype.createAttrMorph = function(attrMorphNum, elementNum, name, escaped, namespace) {
var morphMethod = escaped ? 'createAttrMorph' : 'createUnsafeAttrMorph';
- var morph = "dom."+morphMethod+"(element"+elementNum+", '"+name+"')";
+ var morph = "dom."+morphMethod+"(element"+elementNum+", '"+name+(namespace ? "', '"+namespace : '')+"')";
this.morphs.push(['attrMorph' + attrMorphNum, morph]);
};
prototype.repairClonedNode = function(blankChildTextNodes, isElementChecked) {
var parent = this.getParent(),
- processing = 'dom.repairClonedNode('+parent+','+
+ processing = 'if (this.cachedFragment) { dom.repairClonedNode('+parent+','+
array(blankChildTextNodes)+
( isElementChecked ? ',true' : '' )+
- ');';
+ '); }';
this.fragmentProcessing.push(
processing
);
};
@@ -1111,10 +1129,11 @@
["./template-visitor","./utils","../htmlbars-util/array-utils","../htmlbars-syntax/utils","exports"],
function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
"use strict";
var TemplateVisitor = __dependency1__["default"];
var processOpcodes = __dependency2__.processOpcodes;
+ var getNamespace = __dependency2__.getNamespace;
var forEach = __dependency3__.forEach;
var isHelper = __dependency4__.isHelper;
function unwrapMustache(mustache) {
if (isHelper(mustache.sexpr)) {
@@ -1284,10 +1303,11 @@
};
HydrationOpcodeCompiler.prototype.attribute = function(attr) {
var value = attr.value;
var escaped = true;
+ var namespace = getNamespace(attr.name) || null;
// TODO: Introduce context specific AST nodes to avoid switching here.
if (value.type === 'TextNode') {
return;
} else if (value.type === 'MustacheStatement') {
@@ -1304,11 +1324,11 @@
this.opcode('shareElement', ++this.elementNum);
this.element = null;
}
var attrMorphNum = this.attrMorphNum++;
- this.opcode('createAttrMorph', attrMorphNum, this.elementNum, attr.name, escaped);
+ this.opcode('createAttrMorph', attrMorphNum, this.elementNum, attr.name, escaped, namespace);
this.opcode('printAttributeHook', attrMorphNum, this.elementNum);
};
HydrationOpcodeCompiler.prototype.elementHelper = function(sexpr) {
prepareSexpr(this, sexpr);
@@ -1840,11 +1860,27 @@
compiler[method].call(compiler);
}
}
}
- __exports__.processOpcodes = processOpcodes;
+ __exports__.processOpcodes = processOpcodes;// ref http://dev.w3.org/html5/spec-LC/namespaces.html
+ var defaultNamespaces = {
+ html: 'http://www.w3.org/1999/xhtml',
+ mathml: 'http://www.w3.org/1998/Math/MathML',
+ svg: 'http://www.w3.org/2000/svg',
+ xlink: 'http://www.w3.org/1999/xlink',
+ xml: 'http://www.w3.org/XML/1998/namespace'
+ };
+
+ function getNamespace(attrName) {
+ var parts = attrName.split(':');
+ if (parts.length > 1) {
+ return defaultNamespaces[parts[0]];
+ }
+ }
+
+ __exports__.getNamespace = getNamespace;
});
define("htmlbars-syntax",
["./htmlbars-syntax/walker","./htmlbars-syntax/builders","./htmlbars-syntax/parser","exports"],
function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
"use strict";
@@ -3668,18 +3704,22 @@
}
__exports__["default"] = tokenHandlers;
});
define("htmlbars-syntax/tokenizer",
- ["../simple-html-tokenizer","./utils","./builders","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+ ["../simple-html-tokenizer","./utils","../htmlbars-util/array-utils","./builders","exports"],
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
"use strict";
var Tokenizer = __dependency1__.Tokenizer;
var isHelper = __dependency2__.isHelper;
- var builders = __dependency3__["default"];
+ var map = __dependency3__.map;
+ var builders = __dependency4__["default"];
Tokenizer.prototype.createAttribute = function(char) {
+ if (this.token.type === 'EndTag') {
+ throw new Error('Invalid end tag: closing tag must not have attributes, in ' + formatTokenInfo(this) + '.');
+ }
this.currentAttribute = builders.attr(char.toLowerCase(), [], null);
this.token.attributes.push(this.currentAttribute);
this.state = 'attributeName';
};
@@ -3692,16 +3732,17 @@
};
Tokenizer.prototype.addToAttributeValue = function(char) {
var value = this.currentAttribute.value;
+ if (!this.currentAttribute.quoted && char === '/') {
+ throw new Error("A space is required between an unquoted attribute value and `/`, in " + formatTokenInfo(this) +
+ '.');
+ }
if (!this.currentAttribute.quoted && value.length > 0 &&
(char.type === 'MustacheStatement' || value[0].type === 'MustacheStatement')) {
- // Get the line number from a mustache, whether it's the one to add or the one already added
- var mustache = char.type === 'MustacheStatement' ? char : value[0],
- line = mustache.loc.start.line;
- throw new Error("Unquoted attribute value must be a single string or mustache (line " + line + ")");
+ throw new Error("Unquoted attribute value must be a single string or mustache (on line " + this.line + ")");
}
if (typeof char === 'object') {
if (char.type === 'MustacheStatement') {
value.push(char);
@@ -3730,18 +3771,20 @@
helpers.push(helper);
};
function prepareAttributeValue(attr) {
var parts = attr.value;
- if (parts.length === 0) {
+ var length = parts.length;
+
+ if (length === 0) {
return builders.text('');
- } else if (parts.length === 1 && parts[0].type === "TextNode") {
+ } else if (length === 1 && parts[0].type === "TextNode") {
return parts[0];
} else if (!attr.quoted) {
return parts[0];
} else {
- return builders.concat(parts.map(prepareConcatPart));
+ return builders.concat(map(parts, prepareConcatPart));
}
}
function prepareConcatPart(node) {
switch (node.type) {
@@ -3750,10 +3793,14 @@
default:
throw new Error("Unsupported node in quoted attribute value: " + node.type);
}
}
+ function formatTokenInfo(tokenizer) {
+ return '`' + tokenizer.token.tagName + '` (on line ' + tokenizer.line + ')';
+ }
+
function unwrapMustache(mustache) {
if (isHelper(mustache.sexpr)) {
return mustache.sexpr;
} else {
return mustache.sexpr.path;
@@ -3955,10 +4002,20 @@
__exports__.equalHTML = equalHTML;// detect weird IE8 html strings
var ie8InnerHTMLTestElement = document.createElement('div');
ie8InnerHTMLTestElement.setAttribute('id', 'womp');
var ie8InnerHTML = (ie8InnerHTMLTestElement.outerHTML.indexOf('id=womp') > -1);
+
+ // detect side-effects of cloning svg elements in IE9-11
+ var ieSVGInnerHTML = (function () {
+ var div = document.createElement('div');
+ var node = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
+ div.appendChild(node);
+ var clone = div.cloneNode(true);
+ return clone.innerHTML === '<svg xmlns="http://www.w3.org/2000/svg" />';
+ })();
+
function normalizeInnerHTML(actualHTML) {
if (ie8InnerHTML) {
// drop newlines in IE8
actualHTML = actualHTML.replace(/\r\n/gm, '');
// downcase ALLCAPS tags in IE8
@@ -3968,10 +4025,20 @@
// quote ids in IE8
actualHTML = actualHTML.replace(/id=([^ >]+)/gi, function(match, id){
return 'id="'+id+'"';
});
}
+ if (ieSVGInnerHTML) {
+ // Replace `<svg xmlns="http://www.w3.org/2000/svg" height="50%" />` with `<svg height="50%"></svg>`, etc.
+ // drop namespace attribute
+ actualHTML = actualHTML.replace(/ xmlns="[^"]+"/, '');
+ // replace self-closing elements
+ actualHTML = actualHTML.replace(/<([A-Z]+) [^\/>]*\/>/gi, function(tag, tagName) {
+ return tag.slice(0, tag.length - 3) + '></' + tagName + '>';
+ });
+ }
+
return actualHTML;
}
__exports__.normalizeInnerHTML = normalizeInnerHTML;// detect weird IE8 checked element string
var checkedInput = document.createElement('input');
@@ -3996,22 +4063,33 @@
define("htmlbars-util/array-utils",
["exports"],
function(__exports__) {
"use strict";
function forEach(array, callback, binding) {
- var i;
+ var i, l;
if (binding === undefined) {
- for (i = 0; i < array.length; i++) {
+ for (i = 0, l = array.length; i < l; i++) {
callback(array[i], i, array);
}
} else {
- for (i = 0; i < array.length; i++) {
+ for (i = 0, l = array.length; i < l; i++) {
callback.call(binding, array[i], i, array);
}
}
}
- __exports__.forEach = forEach;
+ __exports__.forEach = forEach;function map(array, callback) {
+ var output = [];
+ var i, l;
+
+ for (i = 0, l = array.length; i < l; i++) {
+ output.push(callback(array[i], i, array));
+ }
+
+ return output;
+ }
+
+ __exports__.map = map;
});
define("htmlbars-util/handlebars/safe-string",
["exports"],
function(__exports__) {
"use strict";
\ No newline at end of file