Skip to content

Commit 06aae7d

Browse files
committed
Event updates and add safe mode.
- Add `safe` flag to call a special safe mode event handler. - Update events API and usage. - Add `hasEventHandler` for call site optimization. - Update handlers.
1 parent 14f882a commit 06aae7d

File tree

2 files changed

+68
-58
lines changed

2 files changed

+68
-58
lines changed

lib/events.js

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,24 @@ const {
1616
const api = {};
1717
module.exports = api;
1818

19-
let _defaultEventHandler = [];
19+
// default handler, store as null or an array
20+
// exposed to allow fast external pre-handleEvent() checks
21+
api.defaultEventHandler = null;
22+
23+
/**
24+
* Check if event handler is in use in options or by default.
25+
*
26+
* This call is used to avoid building event structures and calling the main
27+
* handleEvent() call. It checks if safe mode is on, an event handler is in the
28+
* processing options, or a default handler was set.
29+
*
30+
* @param {object} options - processing options:
31+
* {boolean} [safe] - flag for Safe Mode.
32+
* {function|object|array} [eventHandler] - an event handler.
33+
*/
34+
api.hasEventHandler = options => {
35+
return options.safe || options.eventHandler || api.defaultEventHandler;
36+
};
2037

2138
/**
2239
* Handle an event.
@@ -28,9 +45,6 @@ let _defaultEventHandler = [];
2845
* handlers should process the event as appropriate. The 'next()' function
2946
* should be called to let the next handler process the event.
3047
*
31-
* The final default handler will use 'console.warn' for events of level
32-
* 'warning'.
33-
*
3448
* @param {object} event - event structure:
3549
* {string} code - event code
3650
* {string} level - severity level, one of: ['warning']
@@ -43,8 +57,10 @@ api.handleEvent = ({
4357
options
4458
}) => {
4559
const handlers = [].concat(
60+
// priority is safe mode handler, options handler, then default handler
61+
options.safe ? api.safeModeEventHandler : [],
4662
options.eventHandler ? _asArray(options.eventHandler) : [],
47-
..._defaultEventHandler
63+
api.defaultEventHandler ? api.defaultEventHandler : []
4864
);
4965
_handle({event, handlers});
5066
};
@@ -78,64 +94,54 @@ function _handle({event, handlers}) {
7894
return doNext;
7995
}
8096

81-
// logs all events and continues
82-
api.logEventHandler = function({event, next}) {
83-
console.warn(`EVENT: ${event.message}`, {
84-
code: event.code,
85-
level: event.level,
86-
details: event.details
87-
});
97+
// safe handler that rejects unsafe warning conditions
98+
api.safeModeEventHandler = function({event, next}) {
99+
// fail on all unsafe warnings
100+
if(event.level === 'warning' && event.tags.includes('unsafe')) {
101+
throw new JsonLdError(
102+
'Safe mode violation.',
103+
'jsonld.SafeModeViolationEvent',
104+
{event}
105+
);
106+
}
88107
next();
89108
};
90109

91-
// fallback to throw errors for any unhandled events
92-
api.unhandledEventHandler = function({event}) {
93-
throw new JsonLdError(
94-
'No handler for event.',
95-
'jsonld.UnhandledEvent',
96-
{event});
110+
// strict handler that rejects all warning conditions
111+
api.strictModeEventHandler = function({event, next}) {
112+
// fail on all warnings
113+
if(event.level === 'warning') {
114+
throw new JsonLdError(
115+
'Strict mode violation.',
116+
'jsonld.StrictModeViolationEvent',
117+
{event}
118+
);
119+
}
120+
next();
97121
};
98122

99-
// throw with event details
100-
api.throwUnacceptableEventHandler = function({event}) {
101-
throw new JsonLdError(
102-
'Unacceptable event occurred.',
103-
'jsonld.UnacceptableEvent',
104-
{event});
123+
// logs all events and continues
124+
api.logEventHandler = function({event, next}) {
125+
console.log(`EVENT: ${event.message}`, {event});
126+
next();
105127
};
106128

107129
// log 'warning' level events
108-
api.logWarningEventHandler = function({event}) {
130+
api.logWarningEventHandler = function({event, next}) {
109131
if(event.level === 'warning') {
110-
console.warn(`WARNING: ${event.message}`, {
111-
code: event.code,
112-
details: event.details
113-
});
132+
console.warn(`WARNING: ${event.message}`, {event});
114133
}
134+
next();
115135
};
116136

117-
// strict handler that rejects warning conditions
118-
api.strictModeEventHandler = [
119-
function({event, next}) {
120-
// fail on all warnings
121-
if(event.level === 'warning') {
122-
throw new JsonLdError(
123-
'Strict mode violation occurred.',
124-
'jsonld.StrictModeViolationEvent',
125-
{event});
126-
}
127-
next();
128-
},
129-
// fail on unhandled events
130-
// TODO: update when events are added that are acceptable in strict mode
131-
api.unhandledEventHandler
132-
];
133-
134-
// log warnings to console or fail
135-
api.basicEventHandler = [
136-
api.logWarningEventHandler,
137-
api.unhandledEventHandler
138-
];
137+
// fallback to throw errors for any unhandled events
138+
api.unhandledEventHandler = function({event}) {
139+
throw new JsonLdError(
140+
'No handler for event.',
141+
'jsonld.UnhandledEvent',
142+
{event}
143+
);
144+
};
139145

140146
/**
141147
* Set default event handler.
@@ -149,5 +155,5 @@ api.basicEventHandler = [
149155
* falsey to unset.
150156
*/
151157
api.setDefaultEventHandler = function({eventHandler} = {}) {
152-
_defaultEventHandler = eventHandler ? _asArray(eventHandler) : [];
158+
api.defaultEventHandler = eventHandler ? _asArray(eventHandler) : null;
153159
};

lib/jsonld.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* @author Dave Longley
55
*
66
* @license BSD 3-Clause License
7-
* Copyright (c) 2011-2019 Digital Bazaar, Inc.
7+
* Copyright (c) 2011-2022 Digital Bazaar, Inc.
88
* All rights reserved.
99
*
1010
* Redistribution and use in source and binary forms, with or without
@@ -81,12 +81,10 @@ const {
8181
} = require('./nodeMap');
8282

8383
const {
84-
basicEventHandler: _basicEventHandler,
8584
logEventHandler: _logEventHandler,
8685
logWarningEventHandler: _logWarningEventHandler,
8786
setDefaultEventHandler: _setDefaultEventHandler,
8887
strictModeEventHandler: _strictModeEventHandler,
89-
throwUnacceptableEventHandler: _throwUnacceptableEventHandler,
9088
unhandledEventHandler: _unhandledEventHandler
9189
} = require('./events');
9290

@@ -129,6 +127,7 @@ const _resolvedContextCache = new LRU({max: RESOLVED_CONTEXT_CACHE_MAX_SIZE});
129127
* unmappable values (or to throw an error when they are detected);
130128
* if this function returns `undefined` then the default behavior
131129
* will be used.
130+
* [safe] true to use safe mode.
132131
* [eventHandler] handler for events.
133132
* [contextResolver] internal use only.
134133
*
@@ -268,6 +267,7 @@ jsonld.compact = async function(input, ctx, options) {
268267
* unmappable values (or to throw an error when they are detected);
269268
* if this function returns `undefined` then the default behavior
270269
* will be used.
270+
* [safe] true to use safe mode.
271271
* [eventHandler] handler for events.
272272
* [contextResolver] internal use only.
273273
*
@@ -422,6 +422,7 @@ jsonld.flatten = async function(input, ctx, options) {
422422
* [requireAll] default @requireAll flag (default: true).
423423
* [omitDefault] default @omitDefault flag (default: false).
424424
* [documentLoader(url, options)] the document loader.
425+
* [safe] true to use safe mode.
425426
* [eventHandler] handler for events.
426427
* [contextResolver] internal use only.
427428
*
@@ -521,6 +522,7 @@ jsonld.frame = async function(input, frame, options) {
521522
* [base] the base IRI to use.
522523
* [expandContext] a context to expand with.
523524
* [documentLoader(url, options)] the document loader.
525+
* [safe] true to use safe mode.
524526
* [eventHandler] handler for events.
525527
* [contextResolver] internal use only.
526528
*
@@ -557,6 +559,7 @@ jsonld.link = async function(input, ctx, options) {
557559
* 'application/n-quads' for N-Quads.
558560
* [documentLoader(url, options)] the document loader.
559561
* [useNative] true to use a native canonize algorithm
562+
* [safe] true to use safe mode.
560563
* [eventHandler] handler for events.
561564
* [contextResolver] internal use only.
562565
*
@@ -614,6 +617,7 @@ jsonld.normalize = jsonld.canonize = async function(input, options) {
614617
* (boolean, integer, double), false not to (default: false).
615618
* [rdfDirection] 'i18n-datatype' to support RDF transformation of
616619
* @direction (default: null).
620+
* [safe] true to use safe mode.
617621
* [eventHandler] handler for events.
618622
*
619623
* @return a Promise that resolves to the JSON-LD document.
@@ -664,6 +668,7 @@ jsonld.fromRDF = async function(dataset, options) {
664668
* [produceGeneralizedRdf] true to output generalized RDF, false
665669
* to produce only standard RDF (default: false).
666670
* [documentLoader(url, options)] the document loader.
671+
* [safe] true to use safe mode.
667672
* [eventHandler] handler for events.
668673
* [contextResolver] internal use only.
669674
*
@@ -758,6 +763,7 @@ jsonld.createNodeMap = async function(input, options) {
758763
* new properties where a node is in the `object` position
759764
* (default: true).
760765
* [documentLoader(url, options)] the document loader.
766+
* [safe] true to use safe mode.
761767
* [eventHandler] handler for events.
762768
* [contextResolver] internal use only.
763769
*
@@ -921,6 +927,7 @@ jsonld.get = async function(url, options) {
921927
* @param localCtx the local context to process.
922928
* @param [options] the options to use:
923929
* [documentLoader(url, options)] the document loader.
930+
* [safe] true to use safe mode.
924931
* [eventHandler] handler for events.
925932
* [contextResolver] internal use only.
926933
*
@@ -1008,13 +1015,10 @@ jsonld.registerRDFParser('application/nquads', NQuads.parse);
10081015
jsonld.url = require('./url');
10091016

10101017
/* Events API and handlers */
1011-
jsonld.setDefaultEventHandler = _setDefaultEventHandler;
1012-
jsonld.basicEventHandler = _basicEventHandler;
10131018
jsonld.logEventHandler = _logEventHandler;
10141019
jsonld.logWarningEventHandler = _logWarningEventHandler;
10151020
jsonld.setDefaultEventHandler = _setDefaultEventHandler;
10161021
jsonld.strictModeEventHandler = _strictModeEventHandler;
1017-
jsonld.throwUnacceptableEventHandler = _throwUnacceptableEventHandler;
10181022
jsonld.unhandledEventHandler = _unhandledEventHandler;
10191023

10201024
/* Utility API */

0 commit comments

Comments
 (0)