log.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. The MIT License (MIT)
  3. Copyright (c) 2014-2020 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
  4. Virtual World Framework Apache 2.0 license (https://github.com/NikolaySuslov/livecodingspace/blob/master/licenses/LICENSE_VWF.md)
  5. */
  6. /// @module vwf/model/stage/log
  7. /// @requires vwf/model/stage
  8. import { Stage } from '/core/vwf/model/stage.js';
  9. class Log extends Stage {
  10. constructor(module) {
  11. //console.log("Stage constructor");
  12. super(module);
  13. }
  14. factory(){
  15. let _self_ = this;
  16. return super.factory().load( this.module,
  17. {
  18. // == Module Definition ====================================================================
  19. initialize: function () {
  20. this.logger = this.model.logger; // steal the model's logger since we're logging for it
  21. }
  22. },
  23. function( modelFunctionName ) {
  24. // == Model API ============================================================================
  25. return function() {
  26. if ( this.model[modelFunctionName] ) {
  27. var logees = Array.prototype.slice.call( arguments );
  28. switch ( modelFunctionName ) {
  29. case "creatingNode": // nodeID, childID, childExtendsID, childImplementsIDs, childSource, childType, childIndex, childName, callback /* ( ready ) */
  30. logees[8] = undefined; // callback /* ( ready ) */
  31. break;
  32. case "creatingProperty":
  33. logees[3] && ( logees[3] = _self_.loggableScript( logees[3] ) ); // propertyGet
  34. logees[4] && ( logees[4] = _self_.loggableScript( logees[4] ) ); // propertySet
  35. break;
  36. case "executing":
  37. logees[1] && ( logees[1] = _self_.loggableScript( logees[1] ) ); // scriptText
  38. break;
  39. case "ticking":
  40. logees = undefined; // no logging for model.ticking()
  41. break;
  42. }
  43. if ( logees ) {
  44. this.logger.tracex.apply( this.logger, [ modelFunctionName ].concat( logees ) );
  45. }
  46. return this.model[modelFunctionName].apply( this.model, arguments );
  47. }
  48. };
  49. }, function( kernelFunctionName ) {
  50. // == Kernel API ===========================================================================
  51. return function() {
  52. var logees = Array.prototype.slice.call( arguments );
  53. switch ( kernelFunctionName ) {
  54. case "createNode": // nodeComponent, [ nodeAnnotation, ] [ baseURI, ] callback /* ( nodeID ) */
  55. _self_.objectIsComponent( logees[0] ) && ( logees[0] = JSON.stringify( _self_.loggableComponent( logees[0] ) ) ); // nodeComponent
  56. break;
  57. case "createChild": // nodeID, childName, childComponent, childURI, callback /* ( childID ) */
  58. _self_.objectIsComponent( logees[2] ) && ( logees[2] = JSON.stringify( _self_.loggableComponent( logees[2] ) ) ); // childComponent
  59. break;
  60. case "createProperty":
  61. logees[3] && ( logees[3] = _self_.loggableScript( logees[3] ) ); // propertyGet
  62. logees[4] && ( logees[4] = _self_.loggableScript( logees[4] ) ); // propertySet
  63. break;
  64. case "execute":
  65. logees[1] && ( logees[1] = _self_.loggableScript( logees[1] ) ); // scriptText
  66. break;
  67. case "time":
  68. logees = undefined; // no logging for kernel.time()
  69. break;
  70. }
  71. if ( logees ) {
  72. this.logger.tracex.apply( this.logger, [ kernelFunctionName ].concat( logees ) );
  73. }
  74. return this.kernel[kernelFunctionName].apply( this.kernel, arguments );
  75. };
  76. } );
  77. }
  78. // == Private functions ========================================================================
  79. objectIsComponent( candidate ) { // TODO: this was copied from vwf.js; find a way to share (use the log stage for incoming logging too?)
  80. var componentAttributes = [
  81. "extends",
  82. "implements",
  83. "source",
  84. "type",
  85. "properties",
  86. "methods",
  87. "events",
  88. "children",
  89. "scripts",
  90. ];
  91. var isComponent = false;
  92. if ( typeof candidate == "object" && candidate != null ) {
  93. componentAttributes.forEach( function( attributeName ) {
  94. isComponent = isComponent || Boolean( candidate[attributeName] );
  95. } );
  96. }
  97. return isComponent;
  98. }
  99. loggableComponent( component ) { // TODO: this was copied from vwf.js; find a way to share (use the log stage for incoming logging too?)
  100. var loggable = {};
  101. for ( var elementName in component ) {
  102. switch ( elementName ) {
  103. case "properties":
  104. loggable.properties = {};
  105. for ( var propertyName in component.properties ) {
  106. var componentPropertyValue = component.properties[propertyName];
  107. var loggablePropertyValue = loggable.properties[propertyName] = {};
  108. if ( this.valueHasAccessors( componentPropertyValue ) ) {
  109. for ( var propertyElementName in componentPropertyValue ) {
  110. if ( propertyElementName == "set" || propertyElementName == "get" ) {
  111. loggablePropertyValue[propertyElementName] = "...";
  112. } else {
  113. loggablePropertyValue[propertyElementName] = componentPropertyValue[propertyElementName];
  114. }
  115. }
  116. } else {
  117. loggable.properties[propertyName] = componentPropertyValue;
  118. }
  119. }
  120. break;
  121. case "children":
  122. loggable.children = {};
  123. for ( var childName in component.children ) {
  124. loggable.children[childName] = {};
  125. }
  126. break;
  127. case "scripts":
  128. loggable.scripts = [];
  129. component.scripts.forEach( function( script ) {
  130. var loggableScript = {};
  131. for ( var scriptElementName in script ) {
  132. loggableScript[scriptElementName] = scriptElementName == "text" ? "..." : script[scriptElementName];
  133. }
  134. loggable.scripts.push( loggableScript );
  135. } );
  136. break;
  137. default:
  138. loggable[elementName] = component[elementName];
  139. break;
  140. }
  141. }
  142. return loggable;
  143. }
  144. valueHasAccessors( candidate ) { // TODO: this was copied from vwf.js; find a way to share (use the log stage for incoming logging too?)
  145. var accessorAttributes = [
  146. "get",
  147. "set",
  148. "value",
  149. ];
  150. var hasAccessors = false;
  151. if ( typeof candidate == "object" && candidate != null ) {
  152. accessorAttributes.forEach( function( attributeName ) {
  153. hasAccessors = hasAccessors || Boolean( candidate[attributeName] );
  154. } );
  155. }
  156. return hasAccessors;
  157. }
  158. loggableScript( scriptText ) {
  159. return ( scriptText || "" ).replace( /\s+/g, " " ).substring( 0, 100 );
  160. }
  161. }
  162. export {
  163. Log
  164. }