@@ -24,13 +24,14 @@ var supportES6Map = require('../utils').supportES6Map;
2424
2525var BYTE_CODES = { } ;
2626
27- function Decoder ( buf ) {
27+ function Decoder ( buf , classCache ) {
2828 DecoderV1 . call ( this , buf ) ;
2929 this . BYTE_CODES = BYTE_CODES ;
3030 this . classes = [ ] ; // {name: classname, fields: []}
3131 this . types = [ ] ;
3232
3333 this . _isLastChunk = false ;
34+ this . classCache = classCache ;
3435}
3536
3637util . inherits ( Decoder , DecoderV1 ) ;
@@ -511,18 +512,45 @@ proto.readType = function () {
511512 return type ;
512513} ;
513514
515+ // properties match with this$\d+ means inner properties
516+ // it is useless for node and is circular structure
517+ var INNER_CLASS_PROPERTY_REG = / ^ t h i s \$ \d + $ / ;
518+ var INNER_CLASS_LABEL = '$$ignore_inner_property$$' ;
519+
514520proto . _readObjectDefinition = function ( ) {
515521 var classname = this . readString ( ) ;
522+
523+ // get class definition from cache
524+ var cacheClz = this . classCache && this . classCache . get ( classname ) ;
525+ if ( cacheClz ) {
526+ this . byteBuffer . skip ( cacheClz . length ) ;
527+ this . classes . push ( cacheClz ) ;
528+ return cacheClz ;
529+ }
530+
531+ var pos = this . byteBuffer . position ( ) ;
516532 var fieldsLength = this . readInt ( ) ;
517533 var fields = [ ] ;
518534 for ( var i = 0 ; i < fieldsLength ; i ++ ) {
519- fields . push ( this . readString ( ) ) ;
535+ var name = this . readString ( ) ;
536+ if ( INNER_CLASS_PROPERTY_REG . test ( name ) ) {
537+ name = INNER_CLASS_LABEL ;
538+ }
539+ fields . push ( name ) ;
520540 }
521541 debug ( '_readObjectDefinition got %s fields: %j' , classname , fields ) ;
522- this . classes . push ( {
542+ var clz = {
523543 name : classname ,
524- fields : fields
525- } ) ;
544+ fields : fields ,
545+ length : this . byteBuffer . position ( ) - pos ,
546+ } ;
547+
548+ this . classes . push ( clz ) ;
549+ // set class definition into cache
550+ if ( this . classCache ) {
551+ this . classCache . set ( clz . name , clz ) ;
552+ }
553+ return clz ;
526554} ;
527555
528556/**
@@ -572,7 +600,7 @@ proto.readObject = function (withType) {
572600 } else {
573601 this . throwError ( 'readObject' , code ) ;
574602 }
575-
603+
576604 var cls = this . classes [ ref ] ;
577605 debug ( 'readObject %s, ref: %s' , cls . name , ref ) ;
578606
@@ -586,7 +614,7 @@ proto.readObject = function (withType) {
586614 for ( var i = 0 ; i < fields . length ; i ++ ) {
587615 var name = fields [ i ] ;
588616 var value = this . read ( withType ) ;
589- if ( ! / ^ t h i s \$ \d + $ / . test ( name ) ) {
617+ if ( name !== INNER_CLASS_LABEL ) {
590618 result . $ [ name ] = value ;
591619 }
592620 }
@@ -773,7 +801,7 @@ utils.addByteCodes(BYTE_CODES, [
773801 * v2.0
774802 * ```
775803 * map ::= M(x4d) [type] (value value)* Z
776- *
804+ *
777805 * @see http://hessian.caucho.com/doc/hessian-serialization.html##map
778806 * ```
779807 * Represents serialized maps and can represent objects.
0 commit comments