diff options
Diffstat (limited to 'node_modules/montage/core/deserializer.js')
-rwxr-xr-x | node_modules/montage/core/deserializer.js | 104 |
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. | ||
20 | var 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 | */ |
22 | var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deserializer.Deserializer# */ { | 26 | var 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. |