From 4725fe200dc7e9f8cc13622adfbb58fc054d8f7e Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Wed, 13 Nov 2019 14:02:53 -0800 Subject: [PATCH 1/9] Use rval rather than activeCtx when processing `@base` and `@vocab`. Resolve relative `@vocab` using expandIri with both vocab and base relative resolution. A relative `@vocab` is only invalid in 1.0. --- CHANGELOG.md | 2 ++ lib/context.js | 21 ++++++++++++--------- tests/test-common.js | 14 +------------- 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8024753..05ad872f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ ### Changed - Default processing mode changed to json-ld-1.1. Allows a 1.1 context to be used after non-1.1 contexts. +- `@vocab` can be relative in 1.0, resolved against either a previous `@vocab`, + `@base` or document base. ### Removed - **BREAKING**: Remove callback API support. This includes removing support diff --git a/lib/context.js b/lib/context.js index 262973b6..5755acd1 100644 --- a/lib/context.js +++ b/lib/context.js @@ -194,7 +194,7 @@ api.process = async ({ // if not set explicitly, set processingMode to "json-ld-1.1" rval.processingMode = - rval.processingMode || activeCtx.processingMode || 'json-ld-1.1'; + rval.processingMode || activeCtx.processingMode; // handle @base if('@base' in ctx) { @@ -205,7 +205,7 @@ api.process = async ({ } else if(_isAbsoluteIri(base)) { base = parseUrl(base); } else if(_isRelativeIri(base)) { - base = parseUrl(prependBase(activeCtx['@base'].href, base)); + base = parseUrl(prependBase(rval['@base'].href, base)); } else { throw new JsonLdError( 'Invalid JSON-LD syntax; the value of "@base" in a ' + @@ -228,10 +228,14 @@ api.process = async ({ '@context must be a string or null.', 'jsonld.SyntaxError', {code: 'invalid vocab mapping', context: ctx}); } else if(!_isAbsoluteIri(value)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; the value of "@vocab" in a ' + - '@context must be an absolute IRI.', - 'jsonld.SyntaxError', {code: 'invalid vocab mapping', context: ctx}); + if(api.processingMode(rval, 1.0)) { + throw new JsonLdError( + 'Invalid JSON-LD syntax; the value of "@vocab" in a ' + + '@context must be an absolute IRI.', + 'jsonld.SyntaxError', {code: 'invalid vocab mapping', context: ctx}); + } + rval['@vocab'] = _expandIri(rval, value, {vocab: true, base: true}, + undefined, undefined, options); } else { rval['@vocab'] = value; } @@ -1086,11 +1090,10 @@ api.getAllContexts = async (input, options) => { */ api.processingMode = (activeCtx, version) => { if(version.toString() >= '1.1') { - return activeCtx.processingMode && + return !activeCtx.processingMode || activeCtx.processingMode >= 'json-ld-' + version.toString(); } else { - return !activeCtx.processingMode || - activeCtx.processingMode === 'json-ld-1.0'; + return activeCtx.processingMode === 'json-ld-1.0'; } }; diff --git a/tests/test-common.js b/tests/test-common.js index f965a787..af819080 100644 --- a/tests/test-common.js +++ b/tests/test-common.js @@ -34,13 +34,9 @@ const TEST_TYPES = { idRegex: [ // terms /compact-manifest.jsonld#tp001$/, - // rel iri - /compact-manifest.jsonld#t0095$/, // type set /compact-manifest.jsonld#t0104$/, /compact-manifest.jsonld#t0105$/, - // rel vocab - /compact-manifest.jsonld#t0107$/, // @type: @none /compact-manifest.jsonld#ttn01$/, /compact-manifest.jsonld#ttn02$/, @@ -117,14 +113,8 @@ const TEST_TYPES = { /expand-manifest.jsonld#t0102$/, // multiple graphs /expand-manifest.jsonld#t0103$/, - // rel iri - /expand-manifest.jsonld#t0092$/, // iris /expand-manifest.jsonld#t0109$/, - // rel vocab - /expand-manifest.jsonld#t0110$/, - /expand-manifest.jsonld#t0111$/, - /expand-manifest.jsonld#t0112$/, // terms beginning with ':' /expand-manifest.jsonld#t0117$/, /expand-manifest.jsonld#t0118$/, @@ -460,10 +450,8 @@ const TEST_TYPES = { /toRdf-manifest.jsonld#t0132$/, // @vocab mapping /toRdf-manifest.jsonld#te075$/, - // rel IRI - /toRdf-manifest.jsonld#te092$/, /toRdf-manifest.jsonld#te109$/, - /toRdf-manifest.jsonld#te110$/, + // Invalid Statement /toRdf-manifest.jsonld#te111$/, /toRdf-manifest.jsonld#te112$/, // index maps From 130069d5b9bf3b6ff1b469be26309cc388a1a474 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Wed, 13 Nov 2019 15:09:30 -0800 Subject: [PATCH 2/9] Check for compactIri yielding an absoluteIri where the scheme matches a term that can be used as a prefix. --- lib/compact.js | 11 +++++++++++ tests/test-common.js | 2 -- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/compact.js b/lib/compact.js index 67aea23f..8814b0de 100644 --- a/lib/compact.js +++ b/lib/compact.js @@ -824,6 +824,17 @@ api.compactIri = ({ return choice; } + // If iri could be confused with a compact IRI using a term in this context, + // signal an error + for(const [term, td] of activeCtx.mappings) { + if(iri.startsWith(term + ':') && td._prefix) { + throw new JsonLdError( + ('Absolute IRI "' + iri + '" confused with prefix "' + term + '"'), + 'jsonld.SyntaxError', + {code: 'IRI confused with prefix', context: activeCtx}); + } + } + // compact IRI relative to base if(!relativeTo.vocab) { return _removeBase(activeCtx['@base'], iri); diff --git a/tests/test-common.js b/tests/test-common.js index af819080..643facbb 100644 --- a/tests/test-common.js +++ b/tests/test-common.js @@ -48,8 +48,6 @@ const TEST_TYPES = { /compact-manifest.jsonld#tpi04$/, /compact-manifest.jsonld#tpi05$/, /compact-manifest.jsonld#tpi06$/, - // IRI confusion - /compact-manifest.jsonld#te002$/, // @propogate /compact-manifest.jsonld#tc026$/, /compact-manifest.jsonld#tc027$/, From d83d7efbc85a97879dd225d1c7792aff5d3c6525 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Wed, 13 Nov 2019 15:30:53 -0800 Subject: [PATCH 3/9] Better checking of absolute IRIs. --- CHANGELOG.md | 1 + lib/context.js | 4 +++- lib/url.js | 2 +- tests/test-common.js | 2 -- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05ad872f..43471165 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ used after non-1.1 contexts. - `@vocab` can be relative in 1.0, resolved against either a previous `@vocab`, `@base` or document base. +- Better checking of absolute IRIs. ### Removed - **BREAKING**: Remove callback API support. This includes removing support diff --git a/lib/context.js b/lib/context.js index 5755acd1..e30a54fd 100644 --- a/lib/context.js +++ b/lib/context.js @@ -779,7 +779,9 @@ function _expandIri(activeCtx, value, relativeTo, localCtx, defined, options) { } // already absolute IRI - return value; + if(_isAbsoluteIri(value)) { + return value; + } } // prepend vocab diff --git a/lib/url.js b/lib/url.js index 5d96e4ff..239e7a5e 100644 --- a/lib/url.js +++ b/lib/url.js @@ -66,7 +66,7 @@ api.prependBase = (base, iri) => { return iri; } // already an absolute IRI - if(iri.indexOf(':') !== -1) { + if(api.isAbsolute(iri)) { return iri; } diff --git a/tests/test-common.js b/tests/test-common.js index 643facbb..6cf6fd14 100644 --- a/tests/test-common.js +++ b/tests/test-common.js @@ -111,8 +111,6 @@ const TEST_TYPES = { /expand-manifest.jsonld#t0102$/, // multiple graphs /expand-manifest.jsonld#t0103$/, - // iris - /expand-manifest.jsonld#t0109$/, // terms beginning with ':' /expand-manifest.jsonld#t0117$/, /expand-manifest.jsonld#t0118$/, From 3cfae0b989908f7ce69fe520edd76cb304e41acd Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Wed, 13 Nov 2019 15:41:44 -0800 Subject: [PATCH 4/9] Terms that beging with a ':' are not considered absolute or compact IRIs. --- CHANGELOG.md | 1 + lib/context.js | 4 ++-- tests/test-common.js | 6 ------ 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43471165..2e6d567c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - `@vocab` can be relative in 1.0, resolved against either a previous `@vocab`, `@base` or document base. - Better checking of absolute IRIs. +- Terms that beging with a ':' are not considered absolute or compact IRIs. ### Removed - **BREAKING**: Remove callback API support. This includes removing support diff --git a/lib/context.js b/lib/context.js index e30a54fd..a134cd8e 100644 --- a/lib/context.js +++ b/lib/context.js @@ -393,7 +393,7 @@ api.createTermDefinition = ( // always compute whether term has a colon as an optimization for // _compactIri const colon = term.indexOf(':'); - mapping._termHasColon = (colon !== -1); + mapping._termHasColon = (colon > 0); if('@reverse' in value) { if('@id' in value) { @@ -757,7 +757,7 @@ function _expandIri(activeCtx, value, relativeTo, localCtx, defined, options) { // split value into prefix:suffix const colon = value.indexOf(':'); - if(colon !== -1) { + if(colon > 0) { const prefix = value.substr(0, colon); const suffix = value.substr(colon + 1); diff --git a/tests/test-common.js b/tests/test-common.js index 6cf6fd14..ce0b1048 100644 --- a/tests/test-common.js +++ b/tests/test-common.js @@ -111,9 +111,6 @@ const TEST_TYPES = { /expand-manifest.jsonld#t0102$/, // multiple graphs /expand-manifest.jsonld#t0103$/, - // terms beginning with ':' - /expand-manifest.jsonld#t0117$/, - /expand-manifest.jsonld#t0118$/, // terms having form of keyword /expand-manifest.jsonld#t0119$/, /expand-manifest.jsonld#t0120$/, @@ -402,9 +399,6 @@ const TEST_TYPES = { idRegex: [ // blank node properties /toRdf-manifest.jsonld#t0118$/, - // terms beginning with ':' - /toRdf-manifest.jsonld#te117$/, - /toRdf-manifest.jsonld#te118$/, // terms having form of keyword /toRdf-manifest.jsonld#te119$/, /toRdf-manifest.jsonld#te120$/, From 223d7d792e4d23e88cf44171a9181236fb6c5401 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Wed, 13 Nov 2019 15:48:25 -0800 Subject: [PATCH 5/9] `@vocab` can be a compact IRI. --- CHANGELOG.md | 2 +- lib/context.js | 15 ++++++--------- tests/test-common.js | 3 --- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e6d567c..84751e8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ ### Changed - Default processing mode changed to json-ld-1.1. Allows a 1.1 context to be used after non-1.1 contexts. -- `@vocab` can be relative in 1.0, resolved against either a previous `@vocab`, +- `@vocab` can be relative or a Compact IRI in 1.1, resolved against either a previous `@vocab`, `@base` or document base. - Better checking of absolute IRIs. - Terms that beging with a ':' are not considered absolute or compact IRIs. diff --git a/lib/context.js b/lib/context.js index a134cd8e..19caf094 100644 --- a/lib/context.js +++ b/lib/context.js @@ -227,17 +227,14 @@ api.process = async ({ 'Invalid JSON-LD syntax; the value of "@vocab" in a ' + '@context must be a string or null.', 'jsonld.SyntaxError', {code: 'invalid vocab mapping', context: ctx}); - } else if(!_isAbsoluteIri(value)) { - if(api.processingMode(rval, 1.0)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; the value of "@vocab" in a ' + - '@context must be an absolute IRI.', - 'jsonld.SyntaxError', {code: 'invalid vocab mapping', context: ctx}); - } + } else if(!_isAbsoluteIri(value) && api.processingMode(rval, 1.0)) { + throw new JsonLdError( + 'Invalid JSON-LD syntax; the value of "@vocab" in a ' + + '@context must be an absolute IRI.', + 'jsonld.SyntaxError', {code: 'invalid vocab mapping', context: ctx}); + } else { rval['@vocab'] = _expandIri(rval, value, {vocab: true, base: true}, undefined, undefined, options); - } else { - rval['@vocab'] = value; } defined.set('@vocab', true); } diff --git a/tests/test-common.js b/tests/test-common.js index ce0b1048..7a37e184 100644 --- a/tests/test-common.js +++ b/tests/test-common.js @@ -197,9 +197,6 @@ const TEST_TYPES = { /expand-manifest.jsonld#tso11$/, // colliding keywords /expand-manifest.jsonld#t0114$/, - // vocab iri/term - /expand-manifest.jsonld#te046$/, - /expand-manifest.jsonld#te047$/, // included /expand-manifest.jsonld#tin01$/, /expand-manifest.jsonld#tin02$/, From a812777c4e5c9ba09cd18ac9e880ac1a0df585fc Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Wed, 13 Nov 2019 16:12:36 -0800 Subject: [PATCH 6/9] Don't use terms with expanded definitions as prefixes in 1.0 mode. --- CHANGELOG.md | 1 + lib/context.js | 10 +++++----- tests/test-common.js | 4 ---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84751e8c..09ba5673 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ `@base` or document base. - Better checking of absolute IRIs. - Terms that beging with a ':' are not considered absolute or compact IRIs. +- Don't use terms with `@prefix`: false, or expanded term definitions to construct compact IRIs. ### Removed - **BREAKING**: Remove callback API support. This includes removing support diff --git a/lib/context.js b/lib/context.js index 19caf094..e151fb47 100644 --- a/lib/context.js +++ b/lib/context.js @@ -445,9 +445,9 @@ api.createTermDefinition = ( } mapping['@id'] = id; // indicate if this term may be used as a compact IRI prefix - mapping._prefix = (!mapping._termHasColon && - id.match(/[:\/\?#\[\]@]$/) && - (simpleTerm || api.processingMode(activeCtx, 1.0))); + mapping._prefix = (simpleTerm && + !mapping._termHasColon && + id.match(/[:\/\?#\[\]@]$/)); } } @@ -770,8 +770,8 @@ function _expandIri(activeCtx, value, relativeTo, localCtx, defined, options) { } // use mapping if prefix is defined - if(activeCtx.mappings.has(prefix)) { - const mapping = activeCtx.mappings.get(prefix); + const mapping = activeCtx.mappings.get(prefix); + if(mapping && mapping._prefix) { return mapping['@id'] + suffix; } diff --git a/tests/test-common.js b/tests/test-common.js index 7a37e184..729a8135 100644 --- a/tests/test-common.js +++ b/tests/test-common.js @@ -32,8 +32,6 @@ const TEST_TYPES = { specVersion: ['json-ld-1.0'], // FIXME idRegex: [ - // terms - /compact-manifest.jsonld#tp001$/, // type set /compact-manifest.jsonld#t0104$/, /compact-manifest.jsonld#t0105$/, @@ -163,8 +161,6 @@ const TEST_TYPES = { /expand-manifest.jsonld#te049$/, // invalid keyword alias /expand-manifest.jsonld#te051$/, - // IRI prefixes - /expand-manifest.jsonld#tpr29$/, // protected null IRI mapping /expand-manifest.jsonld#tpr28$/, // remote From 3d18f9d6066b68a7e3f5d7cbb1871b84553c3ed2 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Thu, 14 Nov 2019 08:16:11 -0800 Subject: [PATCH 7/9] Apply suggestions fro @dlongleym code review Co-Authored-By: Dave Longley --- CHANGELOG.md | 2 +- lib/compact.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09ba5673..ee1a4fc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ - `@vocab` can be relative or a Compact IRI in 1.1, resolved against either a previous `@vocab`, `@base` or document base. - Better checking of absolute IRIs. -- Terms that beging with a ':' are not considered absolute or compact IRIs. +- Terms that beggining with a ':' are not considered absolute or compact IRIs. - Don't use terms with `@prefix`: false, or expanded term definitions to construct compact IRIs. ### Removed diff --git a/lib/compact.js b/lib/compact.js index 8814b0de..d4a9c237 100644 --- a/lib/compact.js +++ b/lib/compact.js @@ -827,9 +827,9 @@ api.compactIri = ({ // If iri could be confused with a compact IRI using a term in this context, // signal an error for(const [term, td] of activeCtx.mappings) { - if(iri.startsWith(term + ':') && td._prefix) { + if(td._prefix && iri.startsWith(term + ':')) { throw new JsonLdError( - ('Absolute IRI "' + iri + '" confused with prefix "' + term + '"'), + (`Absolute IRI "${iri}" confused with prefix "${term}".`), 'jsonld.SyntaxError', {code: 'IRI confused with prefix', context: activeCtx}); } From 804f0a7f78cf1cdcb66fa0ef3453716139dbdd3c Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Thu, 14 Nov 2019 12:53:22 -0800 Subject: [PATCH 8/9] Fix check for term having _prefix. --- lib/compact.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compact.js b/lib/compact.js index d4a9c237..e7ad3861 100644 --- a/lib/compact.js +++ b/lib/compact.js @@ -827,7 +827,7 @@ api.compactIri = ({ // If iri could be confused with a compact IRI using a term in this context, // signal an error for(const [term, td] of activeCtx.mappings) { - if(td._prefix && iri.startsWith(term + ':')) { + if(td && td._prefix && iri.startsWith(term + ':')) { throw new JsonLdError( (`Absolute IRI "${iri}" confused with prefix "${term}".`), 'jsonld.SyntaxError', From c5ab700767b85aaccb1a281964a80b5e6acd1d70 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Thu, 14 Nov 2019 12:57:51 -0800 Subject: [PATCH 9/9] Apply suggestions from @davidlehn code review Co-Authored-By: David I. Lehn --- CHANGELOG.md | 4 ++-- lib/compact.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee1a4fc6..01f734a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,8 +13,8 @@ - `@vocab` can be relative or a Compact IRI in 1.1, resolved against either a previous `@vocab`, `@base` or document base. - Better checking of absolute IRIs. -- Terms that beggining with a ':' are not considered absolute or compact IRIs. -- Don't use terms with `@prefix`: false, or expanded term definitions to construct compact IRIs. +- Terms that begin with a ':' are not considered absolute or compact IRIs. +- Don't use terms with `"@prefix": false` or expanded term definitions to construct compact IRIs. ### Removed - **BREAKING**: Remove callback API support. This includes removing support diff --git a/lib/compact.js b/lib/compact.js index e7ad3861..8206d618 100644 --- a/lib/compact.js +++ b/lib/compact.js @@ -829,7 +829,7 @@ api.compactIri = ({ for(const [term, td] of activeCtx.mappings) { if(td && td._prefix && iri.startsWith(term + ':')) { throw new JsonLdError( - (`Absolute IRI "${iri}" confused with prefix "${term}".`), + `Absolute IRI "${iri}" confused with prefix "${term}".`, 'jsonld.SyntaxError', {code: 'IRI confused with prefix', context: activeCtx}); }