Update to latest jsonld.js, add Future API support.
- Use DOM Future API that is a part of new jsonld.js in playground
and in WebIDL test.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/playground/Future.js Wed Apr 24 17:06:07 2013 -0400
@@ -0,0 +1,392 @@
+// Copyright (C) 2013:
+// Alex Russell <slightlyoff@chromium.org>
+// Yehuda Katz
+//
+// Use of this source code is governed by
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// FIXME(slightlyoff):
+// - Document "npm test"
+// - Change global name from "Future" to something less conflicty
+(function(global, browserGlobal, underTest) {
+"use strict";
+
+// FIXME(slighltyoff):
+// * aggregates + tests
+// * check on fast-forwarding
+
+underTest = !!underTest;
+
+//
+// Async Utilities
+//
+
+// Borrowed from RSVP.js
+var async;
+
+var MutationObserver = browserGlobal.MutationObserver ||
+ browserGlobal.WebKitMutationObserver;
+var Future;
+
+if (typeof process !== 'undefined' &&
+ {}.toString.call(process) === '[object process]') {
+ async = function(callback, binding) {
+ process.nextTick(function() {
+ callback.call(binding);
+ });
+ };
+} else if (MutationObserver) {
+ var queue = [];
+
+ var observer = new MutationObserver(function() {
+ var toProcess = queue.slice();
+ queue = [];
+
+ toProcess.forEach(function(tuple) {
+ var callback = tuple[0], binding = tuple[1];
+ callback.call(binding);
+ });
+ });
+
+ var element = document.createElement('div');
+ observer.observe(element, { attributes: true });
+
+ // Chrome Memory Leak: https://bugs.webkit.org/show_bug.cgi?id=93661
+ window.addEventListener('unload', function(){
+ observer.disconnect();
+ observer = null;
+ });
+
+ async = function(callback, binding) {
+ queue.push([callback, binding]);
+ element.setAttribute('drainQueue', 'drainQueue');
+ };
+} else {
+ async = function(callback, binding) {
+ setTimeout(function() {
+ callback.call(binding);
+ }, 1);
+ };
+}
+
+//
+// Object Model Utilities
+//
+
+// defineProperties utilities
+var _readOnlyProperty = function(v) {
+ return {
+ enumerable: true,
+ configurable: false,
+ get: v
+ };
+};
+
+var _method = function(v, e, c, w) {
+ return {
+ enumerable: !!(e || 0),
+ configurable: !!(c || 1),
+ writable: !!(w || 1),
+ value: v || function() {}
+ };
+};
+
+var _pseudoPrivate = function(v) { return _method(v, 0, 1, 0); };
+var _public = function(v) { return _method(v, 1); };
+
+//
+// Futures Utilities
+//
+
+var isThenable = function(any) {
+ try {
+ var f = any.then;
+ if (typeof f == "function") {
+ return true;
+ }
+ } catch (e) { /*squelch*/ }
+ return false;
+};
+
+var AlreadyResolved = function(name) {
+ Error.call(this, name);
+};
+AlreadyResolved.prototype = Object.create(Error.prototype);
+
+var Backlog = function() {
+ var bl = [];
+ bl.pump = function(value) {
+ async(function() {
+ var l = bl.length;
+ var x = 0;
+ while(x < l) {
+ x++;
+ bl.shift()(value);
+ }
+ });
+ };
+ return bl;
+};
+
+//
+// Resolver Constuctor
+//
+
+var Resolver = function(future,
+ acceptCallbacks,
+ rejectCallbacks,
+ setValue,
+ setError,
+ setState) {
+ var isResolved = false;
+
+ var resolver = this;
+ var accept = function(value) {
+ async(function() {
+ setState("accepted");
+ setValue(value);
+ acceptCallbacks.pump(value);
+ });
+ };
+ var reject = function(reason) {
+ async(function() {
+ setState("rejected");
+ setError(reason);
+ rejectCallbacks.pump(reason);
+ });
+ };
+ var resolve = function(value) {
+ if (isThenable(value)) {
+ var funcName = (typeof value.done == "function") ? "done" : "then";
+ value[funcName](resolve, reject);
+ return;
+ }
+ accept(value);
+ };
+ var ifNotResolved = function(func) {
+ return function(value) {
+ if (!isResolved) {
+ isResolved = true;
+ func(value);
+ } else {
+ if (typeof console != "undefined") {
+ console.error("Cannot resolve a Future mutliple times.");
+ }
+ }
+ }
+ };
+
+ // Indirectly resolves the Future, chaining any passed Future's resolution
+ this.resolve = ifNotResolved(resolve);
+
+ // Directly accepts the future, no matter what value's type is
+ this.accept = ifNotResolved(accept);
+
+ // Rejects the future
+ this.reject = ifNotResolved(reject);
+
+ this.cancel = function() { resolver.reject(new Error("Cancel")); };
+ this.timeout = function() { resolver.reject(new Error("Timeout")); };
+
+ if (underTest) {
+ Object.defineProperties(this, {
+ _isResolved: _readOnlyProperty(function() { return isResolved; }),
+ });
+ }
+
+ setState("pending");
+};
+
+//
+// Future Constuctor
+//
+
+var Future = function(init) {
+ var acceptCallbacks = new Backlog();
+ var rejectCallbacks = new Backlog();
+ var value;
+ var error;
+ var state = "pending";
+
+ if (underTest) {
+ Object.defineProperties(this, {
+ _value: _readOnlyProperty(function() { return value; }),
+ _error: _readOnlyProperty(function() { return error; }),
+ _state: _readOnlyProperty(function() { return state; }),
+ });
+ }
+
+ Object.defineProperties(this, {
+ _addAcceptCallback: _pseudoPrivate(
+ function(cb) {
+ acceptCallbacks.push(cb);
+ if (state == "accepted") {
+ acceptCallbacks.pump(value);
+ }
+ }
+ ),
+ _addRejectCallback: _pseudoPrivate(
+ function(cb) {
+ rejectCallbacks.push(cb);
+ if (state == "rejected") {
+ rejectCallbacks.pump(error);
+ }
+ }
+ ),
+ });
+ var r = new Resolver(this,
+ acceptCallbacks, rejectCallbacks,
+ function(v) { value = v; },
+ function(e) { error = e; },
+ function(s) { state = s; })
+ try {
+ if (init) { init(r); }
+ } catch(e) {
+ r.reject(e);
+ }
+};
+
+//
+// Consructor
+//
+
+var isCallback = function(any) {
+ return (typeof any == "function");
+};
+
+// Used in .then()
+var wrap = function(callback, resolver, disposition) {
+ if (!isCallback(callback)) {
+ // If we don't get a callback, we want to forward whatever resolution we get
+ return resolver[disposition].bind(resolver);
+ }
+
+ return function() {
+ try {
+ var r = callback.apply(null, arguments);
+ resolver.resolve(r);
+ } catch(e) {
+ // Exceptions reject the resolver
+ resolver.reject(e);
+ }
+ };
+};
+
+var addCallbacks = function(onaccept, onreject, scope) {
+ if (isCallback(onaccept)) {
+ scope._addAcceptCallback(onaccept);
+ }
+ if (isCallback(onreject)) {
+ scope._addRejectCallback(onreject);
+ }
+ return scope;
+};
+
+//
+// Prototype properties
+//
+
+Future.prototype = Object.create(null, {
+ "then": _public(function(onaccept, onreject) {
+ // The logic here is:
+ // We return a new Future whose resolution merges with the return from
+ // onaccept() or onerror(). If onaccept() returns a Future, we forward
+ // the resolution of that future to the resolution of the returned
+ // Future.
+ var f = this;
+ return new Future(function(r) {
+ addCallbacks(wrap(onaccept, r, "resolve"),
+ wrap(onreject, r, "reject"), f);
+ });
+ }),
+ "done": _public(function(onaccept, onreject) {
+ return addCallbacks(onaccept, onreject, this);
+ }),
+ "catch": _public(function(onreject) {
+ return addCallbacks(null, onreject, this);
+ }),
+});
+
+//
+// Statics
+//
+
+Future.isThenable = isThenable;
+
+var toFuture = function(valueOrFuture) {
+ if (Future.isThenable(valueOrFuture)) {
+ return valueOrFuture;
+ } else {
+ return new Future(function(r) {
+ r.resolve(valueOrFuture);
+ });
+ }
+};
+
+var toFutureList = function(list) {
+ return Array.prototype.slice.call(list).map(toFuture);
+};
+
+/*
+Future.some = function() {
+ // TODO(slightlyoff)
+ var futures = toFutureList(arguments);
+};
+*/
+
+Future.any = function(/*...futuresOrValues*/) {
+ var futures = toFutureList(arguments);
+ return new Future(function(r) {
+ if (!futures.length) {
+ r.reject("No futures passed to Future.any()");
+ } else {
+ var count = 0;
+ var accumulateFailures = function(e) {
+ count++;
+ if (count == futures.length) {
+ r.reject();
+ }
+ };
+ futures.forEach(function(f, idx) {
+ f.done(r.resolve, accumulateFailures);
+ });
+ }
+ });
+};
+
+Future.every = function(/*...futuresOrValues*/) {
+ var futures = toFutureList(arguments);
+ return new Future(function(r) {
+ if (!futures.length) {
+ r.reject("No futures passed to Future.every()");
+ } else {
+ var values = new Array(futures.length);
+ var count = 0;
+ var accumulate = function(idx, v) {
+ count++;
+ values[idx] = v;
+ if (count == futures.length) {
+ r.resolve(values);
+ }
+ };
+ futures.forEach(function(f, idx) {
+ f.done(accumulate.bind(null, idx), r.reject);
+ });
+ }
+ });
+};
+
+//
+// Export
+//
+
+if(typeof module === 'object' && module.exports) {
+ module.exports = Future;
+}
+else {
+ global.Future = Future;
+}
+
+})(this,
+ (typeof window !== 'undefined') ? window : {},
+ this.runningUnderTest||false);
--- a/playground/index.html Tue Apr 23 18:16:26 2013 +0200
+++ b/playground/index.html Wed Apr 24 17:06:07 2013 -0400
@@ -17,6 +17,7 @@
<script type="text/javascript" src="../common/prettify.js"></script>
<script type="text/javascript" src="../common/lang-jsonld.js"></script>
<script type="text/javascript" src="../common/lang-nquads.js"></script>
+ <script type="text/javascript" src="Future.js"></script>
<script type="text/javascript" src="jsonld.js"></script>
<script type="text/javascript" src="playground.js"></script>
<script type="text/javascript" src="playground-examples.js"></script>
--- a/playground/jsonld.js Tue Apr 23 18:16:26 2013 +0200
+++ b/playground/jsonld.js Wed Apr 24 17:06:07 2013 -0400
@@ -69,14 +69,18 @@
options = options || {};
if(ctx === null) {
- return callback(new JsonLdError(
+ return jsonld.nextTick(function() {
+ callback(new JsonLdError(
'The compaction context must not be null.',
'jsonld.CompactError'));
+ });
}
// nothing to compact
if(input === null) {
- return callback(null, null);
+ return jsonld.nextTick(function() {
+ callback(null, null);
+ });
}
// set default options
@@ -100,10 +104,12 @@
}
var expand = function(input, options, callback) {
- if(options.skipExpansion) {
- return callback(null, input);
- }
- jsonld.expand(input, options, callback);
+ jsonld.nextTick(function() {
+ if(options.skipExpansion) {
+ return callback(null, input);
+ }
+ jsonld.expand(input, options, callback);
+ });
};
// expand input then do compaction
@@ -235,36 +241,38 @@
options.keepFreeFloatingNodes = false;
}
- // retrieve all @context URLs in the input
- input = _clone(input);
- _retrieveContextUrls(input, options, function(err, input) {
- if(err) {
- return callback(err);
- }
- try {
- // do expansion
- var activeCtx = _getInitialContext(options);
- var expanded = new Processor().expand(
- activeCtx, null, input, options, false);
-
- // optimize away @graph with no other properties
- if(_isObject(expanded) && ('@graph' in expanded) &&
- Object.keys(expanded).length === 1) {
- expanded = expanded['@graph'];
- }
- else if(expanded === null) {
- expanded = [];
- }
-
- // normalize to an array
- if(!_isArray(expanded)) {
- expanded = [expanded];
- }
- callback(null, expanded);
- }
- catch(ex) {
- callback(ex);
- }
+ jsonld.nextTick(function() {
+ // retrieve all @context URLs in the input
+ input = _clone(input);
+ _retrieveContextUrls(input, options, function(err, input) {
+ if(err) {
+ return callback(err);
+ }
+ try {
+ // do expansion
+ var activeCtx = _getInitialContext(options);
+ var expanded = new Processor().expand(
+ activeCtx, null, input, options, false);
+
+ // optimize away @graph with no other properties
+ if(_isObject(expanded) && ('@graph' in expanded) &&
+ Object.keys(expanded).length === 1) {
+ expanded = expanded['@graph'];
+ }
+ else if(expanded === null) {
+ expanded = [];
+ }
+
+ // normalize to an array
+ if(!_isArray(expanded)) {
+ expanded = [expanded];
+ }
+ callback(null, expanded);
+ }
+ catch(ex) {
+ callback(ex);
+ }
+ });
});
};
@@ -619,21 +627,23 @@
}
}
- // handle special format
- if(options.format) {
- // supported formats
- if(options.format in _rdfParsers) {
- dataset = _rdfParsers[options.format](dataset);
- }
- else {
- throw new JsonLdError(
- 'Unknown input format.',
- 'jsonld.UnknownFormat', {format: options.format});
- }
- }
-
- // convert from RDF
- new Processor().fromRDF(dataset, options, callback);
+ jsonld.nextTick(function() {
+ // handle special format
+ if(options.format) {
+ // supported formats
+ if(options.format in _rdfParsers) {
+ dataset = _rdfParsers[options.format](dataset);
+ }
+ else {
+ throw new JsonLdError(
+ 'Unknown input format.',
+ 'jsonld.UnknownFormat', {format: options.format});
+ }
+ }
+
+ // convert from RDF
+ new Processor().fromRDF(dataset, options, callback);
+ });
};
/**
@@ -715,16 +725,100 @@
'jsonld.ContextUrlError'), url);
};
+/* Futures/Promises API */
+
+jsonld.futures = jsonld.promises = function() {
+ var Future = _nodejs ? require('./Future') : window.Future;
+
+ // converts a node.js async op into a future w/boxed resolved value(s)
+ function futurize(op) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return new Future(function(resolver) {
+ op.apply(null, args.concat(function(err, value) {
+ if(err) {
+ resolver.reject(err);
+ }
+ else {
+ resolver.resolve(value);
+ }
+ }));
+ });
+ }
+
+ // converts a load context promise callback to a node-style callback
+ function createContextLoader(promise) {
+ return function(url, callback) {
+ promise(url).then(
+ // success
+ function(remoteContext) {
+ callback(null, remoteContext.url, remoteContext.context);
+ },
+ // failure
+ callback
+ );
+ };
+ }
+
+ var api = {};
+ api.expand = function(input) {
+ var options = (arguments.length > 1) ? arguments[1] : {};
+ if('loadContext' in options) {
+ options.loadContext = createContextLoader(options.loadContext);
+ }
+ return futurize(jsonld.expand, input, options);
+ };
+ api.compact = function(input, ctx) {
+ var options = (arguments.length > 2) ? arguments[2] : {};
+ if('loadContext' in options) {
+ options.loadContext = createContextLoader(options.loadContext);
+ }
+ var compact = function(input, ctx, options, callback) {
+ // ensure only one value is returned in callback
+ jsonld.compact(input, ctx, options, function(err, compacted) {
+ callback(err, compacted);
+ });
+ };
+ return futurize(compact, input, ctx, options);
+ };
+ api.flatten = function(input, ctx) {
+ var options = (arguments.length > 2) ? arguments[2] : {};
+ if('loadContext' in options) {
+ options.loadContext = createContextLoader(options.loadContext);
+ }
+ return futurize(jsonld.flatten, input, ctx, options);
+ };
+ api.frame = function(input, frame) {
+ var options = (arguments.length > 2) ? arguments[2] : {};
+ if('loadContext' in options) {
+ options.loadContext = createContextLoader(options.loadContext);
+ }
+ return futurize(jsonld.frame, input, frame, options);
+ };
+ api.fromRDF = function(dataset) {
+ var options = (arguments.length > 1) ? arguments[1] : {};
+ return futurize(jsonld.fromRDF, dataset, options);
+ };
+ api.toRDF = function(input) {
+ var options = (arguments.length > 1) ? arguments[1] : {};
+ if('loadContext' in options) {
+ options.loadContext = createContextLoader(options.loadContext);
+ }
+ return futurize(jsonld.toRDF, input, options);
+ };
+ api.normalize = function(input) {
+ var options = (arguments.length > 1) ? arguments[1] : {};
+ if('loadContext' in options) {
+ options.loadContext = createContextLoader(options.loadContext);
+ }
+ return futurize(jsonld.normalize, input, options);
+ };
+ return api;
+};
+
/* WebIDL API */
function JsonLdProcessor() {};
-JsonLdProcessor.prototype.expand = jsonld.expand;
-JsonLdProcessor.prototype.compact = jsonld.compact;
-JsonLdProcessor.prototype.flatten = jsonld.flatten;
-JsonLdProcessor.prototype.frame = jsonld.frame;
-JsonLdProcessor.prototype.fromRDF = jsonld.fromRDF;
-JsonLdProcessor.prototype.toRDF = jsonld.toRDF;
-JsonLdProcessor.prototype.normalize = jsonld.normalize;
+JsonLdProcessor.prototype = jsonld.futures();
JsonLdProcessor.prototype.toString = function() {
return '[object JsonLdProcessor]';
};
--- a/playground/playground.js Tue Apr 23 18:16:26 2013 +0200
+++ b/playground/playground.js Wed Apr 24 17:06:07 2013 -0400
@@ -190,80 +190,68 @@
};
/**
- * Performs the JSON-LD API action based on the active tab.
+ * Returns a Future to performs the JSON-LD API action based on the active
+ * tab.
*
* @param input the JSON-LD object input or null no error.
* @param param the JSON-LD param to use.
- * @param callback(err) called once the operation completes.
*/
- playground.performAction = function(input, param, callback) {
- // set base IRI
- var options = {base: document.baseURI};
+ playground.performAction = function(input, param) {
+ return new Future(function(resolver) {
+ var processor = new jsonld.JsonLdProcessor();
- if(playground.activeTab === 'tab-compacted') {
- jsonld.compact(input, param, options, function(err, compacted) {
- if(err) {
- return callback(err);
- }
- $('#compacted').html(js_beautify(
- playground.htmlEscape(JSON.stringify(compacted)),
- {'indent_size': 2}).replace(/\n/g, '<br>'));
- callback();
- });
- }
- else if(playground.activeTab === 'tab-expanded') {
- jsonld.expand(input, options, function(err, expanded) {
- if(err) {
- return callback(err);
- }
- $('#expanded').html(js_beautify(
- playground.htmlEscape(JSON.stringify(expanded)),
- {'indent_size': 2}).replace(/\n/g, '<br>'));
- callback();
- });
- }
- else if(playground.activeTab === 'tab-flattened') {
- jsonld.flatten(input, param, options, function(err, flattened) {
- if(err) {
- return callback(err);
- }
- $('#flattened').html(js_beautify(
- playground.htmlEscape(JSON.stringify(flattened)),
- {'indent_size': 2}).replace(/\n/g, '<br>'));
- callback();
- });
- }
- else if(playground.activeTab === 'tab-framed') {
- jsonld.frame(input, param, options, function(err, framed) {
- if(err) {
- return callback(err);
- }
- $('#framed').html(js_beautify(
- playground.htmlEscape(JSON.stringify(framed)),
- {'indent_size': 2}).replace(/\n/g, '<br>'));
- callback();
- });
- }
- else if(playground.activeTab === 'tab-nquads') {
- options.format = 'application/nquads';
- jsonld.toRDF(input, options, function(err, nquads) {
- if(err) {
- return callback(err);
- }
- $('#nquads').html(playground.htmlEscape(nquads).replace(/\n/g, '<br>'));
- callback();
- });
- }
- else if(playground.activeTab === 'tab-normalized') {
- options.format = 'application/nquads';
- jsonld.normalize(input, options, function(err, normalized) {
- if(err) {
- return callback(err);
- }
- $('#normalized').html(playground.htmlEscape(normalized).replace(/\n/g, '<br>'));
- callback();
- });
- }
+ // set base IRI
+ var options = {base: document.baseURI};
+
+ if(playground.activeTab === 'tab-compacted') {
+ processor.compact(input, param, options).done(function(compacted) {
+ $('#compacted').html(js_beautify(
+ playground.htmlEscape(JSON.stringify(compacted)),
+ {'indent_size': 2}).replace(/\n/g, '<br>'));
+ resolver.resolve();
+ }, resolver.reject);
+ }
+ else if(playground.activeTab === 'tab-expanded') {
+ processor.expand(input, options).done(function(expanded) {
+ $('#expanded').html(js_beautify(
+ playground.htmlEscape(JSON.stringify(expanded)),
+ {'indent_size': 2}).replace(/\n/g, '<br>'));
+ resolver.resolve();
+ }, resolver.reject);
+ }
+ else if(playground.activeTab === 'tab-flattened') {
+ processor.flatten(input, param, options).done(function(flattened) {
+ $('#flattened').html(js_beautify(
+ playground.htmlEscape(JSON.stringify(flattened)),
+ {'indent_size': 2}).replace(/\n/g, '<br>'));
+ resolver.resolve();
+ }, resolver.reject);
+ }
+ else if(playground.activeTab === 'tab-framed') {
+ processor.frame(input, param, options).done(function(framed) {
+ $('#framed').html(js_beautify(
+ playground.htmlEscape(JSON.stringify(framed)),
+ {'indent_size': 2}).replace(/\n/g, '<br>'));
+ resolver.resolve();
+ }, resolver.reject);
+ }
+ else if(playground.activeTab === 'tab-nquads') {
+ options.format = 'application/nquads';
+ processor.toRDF(input, options).done(function(nquads) {
+ $('#nquads').html(
+ playground.htmlEscape(nquads).replace(/\n/g, '<br>'));
+ resolver.resolve();
+ }, resolver.reject);
+ }
+ else if(playground.activeTab === 'tab-normalized') {
+ options.format = 'application/nquads';
+ processor.normalize(input, options).done(function(normalized) {
+ $('#normalized').html(
+ playground.htmlEscape(normalized).replace(/\n/g, '<br>'));
+ resolver.resolve();
+ }, resolver.reject);
+ }
+ });
};
/**
@@ -326,13 +314,7 @@
}
// no errors, perform the action and display the output
- playground.performAction(input, param, function(err) {
- if(err) {
- // FIXME: add better error handling output
- $('#processing-errors').text(JSON.stringify(err));
- return;
- }
-
+ playground.performAction(input, param).done(function() {
// generate a link for current data
var link = '?json-ld=' + encodeURIComponent(JSON.stringify(input));
if($('#frame').val().length > 0) {
@@ -358,6 +340,9 @@
// start the colorization delay
playground.checkColorizeDelay(true);
+ }, function(err) {
+ // FIXME: add better error handling output
+ $('#processing-errors').text(JSON.stringify(err));
});
};
--- a/test-suite/idltest/index.html Tue Apr 23 18:16:26 2013 +0200
+++ b/test-suite/idltest/index.html Wed Apr 24 17:06:07 2013 -0400
@@ -5,12 +5,12 @@
<title>JSON-LD idlharness test</title>
<link rel="author" title="W3C" href="http://www.w3.org/" />
<link rel="help" href="http://www.w3.org/TR/json-ld-api/#jsonldprocessor" />
-<link rel="help" href="http://json-ld.org/spec/latest/json-ld-api/#jsonldcallback" />
<link rel="help" href="http://json-ld.org/spec/latest/json-ld-api/#loadcontextcallback" />
-<link rel="help" href="http://json-ld.org/spec/latest/json-ld-api/#contextloadedcallback" />
+<link rel="help" href="http://json-ld.org/spec/latest/json-ld-api/#remotecontext" />
<link rel="help" href="http://json-ld.org/spec/latest/json-ld-api/#jsonldoptions" />
<link rel="help" href="http://json-ld.org/spec/latest/json-ld-api/#jsonlderror" />
<link rel="help" href="http://json-ld.org/spec/latest/json-ld-api/#jsonlderrorcode" />
+<script src="../../playground/Future.js"></script>
<script src="../../playground/jsonld.js"></script>
<script src="http://w3c-test.org/resources/testharness.js"></script>
<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
@@ -28,22 +28,20 @@
<pre id="idl">
[Constructor]
interface JsonLdProcessor {
- void compact (JsonLdInput input, JsonLdContext context, JsonLdOptions options, JsonLdCallback callback);
- void compact (JsonLdInput input, JsonLdContext context, JsonLdCallback callback);
- void expand (JsonLdInput input, JsonLdOptions options, JsonLdCallback callback);
- void expand (JsonLdInput input, JsonLdCallback callback);
- void flatten (JsonLdInput input, JsonLdContext? context, JsonLdOptions options, JsonLdCallback callback);
- void flatten (JsonLdInput input, JsonLdContext? context, JsonLdCallback callback);
+ Future compact (JsonLdInput input, JsonLdContext context, optional JsonLdOptions options);
+ Future expand (JsonLdInput input, optional JsonLdOptions options);
+ Future flatten (JsonLdInput input, JsonLdContext? context, optional JsonLdOptions options);
};
typedef (object or object[] or DOMString) JsonLdInput;
typedef (object or DOMString) JsonLdContext;
-callback JsonLdCallback = void (JsonLdError error, optional (object or object[]) document);
+callback LoadContextCallback = Future (DOMString url);
-callback LoadContextCallback = void (DOMString url, ContextLoadedCallback callback);
-
-callback ContextLoadedCallback = void (JsonLdError error, optional DOMString url, optional DOMString context);
+dictionary RemoteContext {
+ DOMString url;
+ DOMString context;
+};
dictionary JsonLdOptions {
DOMString base;