aboutsummaryrefslogtreecommitdiff
path: root/node_modules/montage/core/deserializer.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/montage/core/deserializer.js')
-rwxr-xr-xnode_modules/montage/core/deserializer.js104
1 files changed, 90 insertions, 14 deletions
diff --git a/node_modules/montage/core/deserializer.js b/node_modules/montage/core/deserializer.js
index 8f1f0831..09635153 100755
--- a/node_modules/montage/core/deserializer.js
+++ b/node_modules/montage/core/deserializer.js
@@ -15,11 +15,17 @@ var Montage = require("montage").Montage,
15 logger = require("core/logger").logger("deserializer"), 15 logger = require("core/logger").logger("deserializer"),
16 Promise = require("core/promise").Promise; 16 Promise = require("core/promise").Promise;
17 17
18// By rebinding eval to a new name, it loses its ability to
19// capture the calling scope.
20var globalEval = eval;
21
18/** 22/**
19 @class module:montage/core/deserializer.Deserializer 23 @class module:montage/core/deserializer.Deserializer
20 @extends module:montage/core/core.Montage 24 @extends module:montage/core/core.Montage
21 */ 25 */
22var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deserializer.Deserializer# */ { 26var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deserializer.Deserializer# */ {
27 _MONTAGE_ID_ATTRIBUTE: {value: "data-montage-id"},
28
23 _objects: {value: null}, 29 _objects: {value: null},
24 /** 30 /**
25 @private 31 @private
@@ -51,6 +57,13 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri
51/** 57/**
52 @private 58 @private
53*/ 59*/
60
61 /**
62 @private
63 */
64 // list of ids that were just created for optimization
65 _optimizedIds: {value: {}},
66
54 _indexedDeserializationUnits: {value: {}}, 67 _indexedDeserializationUnits: {value: {}},
55 68
56 __sharedDocument: { 69 __sharedDocument: {
@@ -365,6 +378,27 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri
365 this._compileAndDeserialize(); 378 this._compileAndDeserialize();
366 return this._compiledDeserializationFunctionString; 379 return this._compiledDeserializationFunctionString;
367 }}, 380 }},
381
382 /**
383 * Optimizes the current serialization for a specific document.
384 * @function
385 * @param {Document} doc The document to optimize against, this document can be modified during optimization.
386 */
387 optimizeForDocument: {
388 value: function(doc) {
389 var idAttributeName = Deserializer._MONTAGE_ID_ATTRIBUTE,
390 elements = doc.querySelectorAll('*[' + idAttributeName + ']'),
391 ids = this._optimizedIds = {};
392
393 for (var i = 0, element; (element = elements[i]); i++) {
394 if (!element.id) {
395 var attribute = element.getAttribute(idAttributeName);
396 element.setAttribute("id", ids[attribute] = "_" + idAttributeName + "_" + attribute);
397 }
398 }
399 }
400 },
401
368/** 402/**
369 @private 403 @private
370*/ 404*/
@@ -374,9 +408,12 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri
374 exportsStrings = "", 408 exportsStrings = "",
375 unitsStrings = "", 409 unitsStrings = "",
376 objectsStrings = "", 410 objectsStrings = "",
411 cleanupStrings = "",
377 valueString, 412 valueString,
378 exports = {}, 413 exports = {},
379 modules = this._modules, 414 modules = this._modules,
415 idsToRemove = [],
416 optimizedIds = this._optimizedIds,
380 requireStrings = [], 417 requireStrings = [],
381 objectNamesCounter = {}, 418 objectNamesCounter = {},
382 label; 419 label;
@@ -408,8 +445,17 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri
408 } 445 }
409 } 446 }
410 447
411 this._compiledDeserializationFunctionString = "(function() {\n" + requireStrings.join("\n") + "\nreturn function(element) {\nvar exports = {};\n" + exportsStrings + "\n\n" + objectsStrings + "\n\n" + unitsStrings + "\nreturn exports;\n}}).call(this)"; 448 if (idsToRemove.length > 0) {
412 //console.log(this._compiledDeserializationFunctionString); 449 cleanupStrings = 'element.getElementById("' + idsToRemove.join('").removeAttribute("id");\nelement.getElementById("') + '").removeAttribute("id");';
450 for (var i = 0, id; (id = idsToRemove[i]); i++) {
451 element.getElementById(idsToRemove[i]).removeAttribute("id");
452 }
453 }
454
455 this._compiledDeserializationFunctionString = "(function() {\n" + requireStrings.join("\n") + "\nreturn function(element) {\nvar exports = {};\n" + exportsStrings + "\n\n" + objectsStrings + "\n\n" + unitsStrings + "\n\n" + cleanupStrings + "\nreturn exports;\n}}).call(this)";
456 if (logger.isDebug) {
457 logger.debug(this._compiledDeserializationFunctionString);
458 }
413 459
414 this._serialization = serialization = null; 460 this._serialization = serialization = null;
415 461
@@ -490,7 +536,7 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri
490 } else if (value === null) { 536 } else if (value === null) {
491 return "null"; 537 return "null";
492 } else if ("#" in value) { 538 } else if ("#" in value) {
493 type = "elementById"; 539 type = "elementByMontageId";
494 value = value["#"]; 540 value = value["#"];
495 } else if ("/" in value) { 541 } else if ("/" in value) {
496 type = "regexp"; 542 type = "regexp";
@@ -502,7 +548,7 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri
502 type = "function"; 548 type = "function";
503 value = value["->"]; 549 value = value["->"];
504 } else if ("." in value && Object.keys(value).length === 1) { 550 } else if ("." in value && Object.keys(value).length === 1) {
505 console.log("Warning: It's not possible to reference elements by class name anymore: " + JSON.stringify(value) + "' in template " + self._origin + "."); 551 console.log("Warning: It's not possible to reference elements by class name anymore: '" + JSON.stringify(value) + "' in template " + self._origin + ".");
506 } 552 }
507 } 553 }
508 554
@@ -529,15 +575,35 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri
529 return '[' + properties.join(",\n") + ']'; 575 return '[' + properties.join(",\n") + ']';
530 break; 576 break;
531 577
532 case "elementById": 578 case "elementByMontageId":
533 if (deserialize) { 579 var id = self._optimizedIds[value],
534 var node = element.getElementById(value); 580 node;
581
582 if (id) {
583 node = element.getElementById(id);
584 idsToRemove.push(id);
585 } else {
586 node = element.querySelector('*[' + Deserializer._MONTAGE_ID_ATTRIBUTE + '="' + value + '"]');
535 if (!node) { 587 if (!node) {
536 console.log("Warning: Element '#" + value + "' not found in template " + self._origin); 588 node = element.getElementById(value);
589 id = value;
537 } 590 }
591 }
592
593 if (!node) {
594 console.log("Warning: Element " + Deserializer._MONTAGE_ID_ATTRIBUTE + "='" + value + "' not found in template " + self._origin);
595 }
596
597 if (deserialize) {
538 parent[key] = node; 598 parent[key] = node;
539 } 599 }
540 return 'element.getElementById("' + value + '")'; 600
601 if (id) {
602 return 'element.getElementById("' + id + '")';
603 } else {
604 // TODO: getElemenyById only here for backwards compatibility
605 return 'element.querySelector(\'*[' + Deserializer._MONTAGE_ID_ATTRIBUTE + '="' + value + '"]\') || element.getElementById("' + value + '")';
606 }
541 break; 607 break;
542 608
543 case "regexp": 609 case "regexp":
@@ -569,7 +635,7 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri
569 case "function": 635 case "function":
570 var source = "function" + (value.name ? " " + value.name : "") + "(" + value.arguments.join(", ") + ") {\n" + value.body + "\n}"; 636 var source = "function" + (value.name ? " " + value.name : "") + "(" + value.arguments.join(", ") + ") {\n" + value.body + "\n}";
571 if (deserialize) { 637 if (deserialize) {
572 parent[key] = (1,eval)('(' + source + ')'); 638 parent[key] = globalEval('(' + source + ')');
573 } 639 }
574 return source; 640 return source;
575 break; 641 break;
@@ -618,7 +684,6 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri
618 // first run, deserialize and create the source of the compiled deserialization function 684 // first run, deserialize and create the source of the compiled deserialization function
619 } else { 685 } else {
620 exports = this._compileAndDeserialize(sourceDocument, true); 686 exports = this._compileAndDeserialize(sourceDocument, true);
621 //console.log(this._compiledDeserializationFunctionString);
622 } 687 }
623 688
624 if (targetDocument) { 689 if (targetDocument) {
@@ -643,6 +708,20 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri
643 }, 708 },
644 709
645 /** 710 /**
711 Deserializes a serialization of a single object using a root element to find elements' references.
712 @function
713 @param {Element} element The element to be cloned and used during deserialization of elements' references.
714 @param {function(object)} callback The callback to be invoked when the object has been fully deserialized.
715 */
716 deserializeObjectWithElement: {
717 value: function(element, callback) {
718 return this.deserializeWithInstancesAndElementForDocument(null, element, null, function(exports) {
719 callback(exports ? exports.root : undefined);
720 });
721 }
722 },
723
724 /**
646 Deserializes all objects. 725 Deserializes all objects.
647 @function 726 @function
648 @param {function(object)} callback The callback to be invoked when the object has been fully deserialized. The function will be called with a dictionary ({label: object}) with all deserialized objects.