@@ -97,10 +97,28 @@ const wrapper = function(jsonld) {
9797/** Registered RDF dataset parsers hashed by content-type. */
9898const _rdfParsers = { } ;
9999
100- // resolved context cache
101- // TODO: consider basing max on context size rather than number
100+ // resolved context caches
101+ // TODO: add controls for cache resource usage
102+ // cache size per document loader
102103const RESOLVED_CONTEXT_CACHE_MAX_SIZE = 100 ;
103- const _resolvedContextCache = new LRU ( { max : RESOLVED_CONTEXT_CACHE_MAX_SIZE } ) ;
104+ // caches are created and indexed per documentLoader
105+ // resources are cleaned up with WeakMap semantics for the documentLoaders
106+ const _resolvedContextCaches = new WeakMap ( ) ;
107+ // default key to use when no documentLoader used
108+ const _defaultDocumentLoaderKey = { } ;
109+
110+ // make a ContextResolver using a per-documentLoader shared cache
111+ function _makeContextResolver ( { documentLoader = _defaultDocumentLoaderKey } ) {
112+ let cache = _resolvedContextCaches . get ( documentLoader ) ;
113+ if ( ! cache ) {
114+ // TODO: consider basing max on context size rather than number
115+ cache = new LRU ( { max : RESOLVED_CONTEXT_CACHE_MAX_SIZE } ) ;
116+ _resolvedContextCaches . set ( documentLoader , cache ) ;
117+ }
118+ return new ContextResolver ( {
119+ sharedCache : cache
120+ } ) ;
121+ }
104122
105123/* Core API */
106124
@@ -152,8 +170,9 @@ jsonld.compact = async function(input, ctx, options) {
152170 skipExpansion : false ,
153171 link : false ,
154172 issuer : new IdentifierIssuer ( '_:b' ) ,
155- contextResolver : new ContextResolver (
156- { sharedCache : _resolvedContextCache } )
173+ contextResolver : _makeContextResolver ( {
174+ documentLoader : options ? options . documentLoader : undefined
175+ } )
157176 } ) ;
158177 if ( options . link ) {
159178 // force skip expansion when linking, "link" is not part of the public
@@ -269,8 +288,9 @@ jsonld.expand = async function(input, options) {
269288 // set default options
270289 options = _setDefaults ( options , {
271290 keepFreeFloatingNodes : false ,
272- contextResolver : new ContextResolver (
273- { sharedCache : _resolvedContextCache } )
291+ contextResolver : _makeContextResolver ( {
292+ documentLoader : options ? options . documentLoader : undefined
293+ } )
274294 } ) ;
275295
276296 // build set of objects that may have @contexts to resolve
@@ -368,8 +388,9 @@ jsonld.flatten = async function(input, ctx, options) {
368388 // set default options
369389 options = _setDefaults ( options , {
370390 base : _isString ( input ) ? input : '' ,
371- contextResolver : new ContextResolver (
372- { sharedCache : _resolvedContextCache } )
391+ contextResolver : _makeContextResolver ( {
392+ documentLoader : options ? options . documentLoader : undefined
393+ } )
373394 } ) ;
374395
375396 // expand input
@@ -423,8 +444,9 @@ jsonld.frame = async function(input, frame, options) {
423444 requireAll : false ,
424445 omitDefault : false ,
425446 bnodesToClear : [ ] ,
426- contextResolver : new ContextResolver (
427- { sharedCache : _resolvedContextCache } )
447+ contextResolver : _makeContextResolver ( {
448+ documentLoader : options ? options . documentLoader : undefined
449+ } )
428450 } ) ;
429451
430452 // if frame is a string, attempt to dereference remote document
@@ -565,8 +587,9 @@ jsonld.normalize = jsonld.canonize = async function(input, options) {
565587 algorithm : 'URDNA2015' ,
566588 skipExpansion : false ,
567589 safe : true ,
568- contextResolver : new ContextResolver (
569- { sharedCache : _resolvedContextCache } )
590+ contextResolver : _makeContextResolver ( {
591+ documentLoader : options ? options . documentLoader : undefined
592+ } )
570593 } ) ;
571594 if ( 'inputFormat' in options ) {
572595 if ( options . inputFormat !== 'application/n-quads' &&
@@ -674,8 +697,9 @@ jsonld.toRDF = async function(input, options) {
674697 options = _setDefaults ( options , {
675698 base : _isString ( input ) ? input : '' ,
676699 skipExpansion : false ,
677- contextResolver : new ContextResolver (
678- { sharedCache : _resolvedContextCache } )
700+ contextResolver : _makeContextResolver ( {
701+ documentLoader : options ? options . documentLoader : undefined
702+ } )
679703 } ) ;
680704
681705 // TODO: support toRDF custom map?
@@ -726,8 +750,9 @@ jsonld.createNodeMap = async function(input, options) {
726750 // set default options
727751 options = _setDefaults ( options , {
728752 base : _isString ( input ) ? input : '' ,
729- contextResolver : new ContextResolver (
730- { sharedCache : _resolvedContextCache } )
753+ contextResolver : _makeContextResolver ( {
754+ documentLoader : options ? options . documentLoader : undefined
755+ } )
731756 } ) ;
732757
733758 // expand input
@@ -774,8 +799,9 @@ jsonld.merge = async function(docs, ctx, options) {
774799
775800 // set default options
776801 options = _setDefaults ( options , {
777- contextResolver : new ContextResolver (
778- { sharedCache : _resolvedContextCache } )
802+ contextResolver : _makeContextResolver ( {
803+ documentLoader : options ? options . documentLoader : undefined
804+ } )
779805 } ) ;
780806
781807 // expand all documents
@@ -926,8 +952,9 @@ jsonld.processContext = async function(
926952 // set default options
927953 options = _setDefaults ( options , {
928954 base : '' ,
929- contextResolver : new ContextResolver (
930- { sharedCache : _resolvedContextCache } )
955+ contextResolver : _makeContextResolver ( {
956+ documentLoader : options ? options . documentLoader : undefined
957+ } )
931958 } ) ;
932959
933960 // return initial context early for null context
0 commit comments