eyeling 1.28.3 → 1.28.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16389,11 +16389,18 @@ function liftBlankRuleVars(premise, conclusion) {
16389
16389
  const mapping = Object.create(null);
16390
16390
  let counter = 0;
16391
16391
 
16392
+ // These variables are implementation details used to correlate one blank
16393
+ // node across the lifted rule body. Their names must not be spellable by
16394
+ // user input; otherwise a user variable such as ?_b1 can capture the
16395
+ // lifted blank node and leak it into the rule head. U+E000 is a private-use
16396
+ // code point and is not accepted by the lexer as part of a variable name.
16397
+ const INTERNAL_BLANK_VAR_PREFIX = '\uE000eyeling_b';
16398
+
16392
16399
  function blankToVar(label) {
16393
16400
  let name = mapping[label];
16394
16401
  if (name === undefined) {
16395
16402
  counter += 1;
16396
- name = `_b${counter}`;
16403
+ name = `${INTERNAL_BLANK_VAR_PREFIX}${counter}`;
16397
16404
  mapping[label] = name;
16398
16405
  }
16399
16406
  return new Var(name);
@@ -16445,7 +16452,7 @@ function liftBlankRuleVars(premise, conclusion) {
16445
16452
  // consumed by the builtin rather than ordinary triple patterns. Keep their
16446
16453
  // local blank nodes as Blank terms so the builtin can treat them as local
16447
16454
  // existentials, and bindings returned from an explicit scope are blank nodes
16448
- // instead of synthetic rule variables such as ?_b1.
16455
+ // instead of synthetic rule variables.
16449
16456
  const keepFormulaBlanks = isLogIncludesLikePredicate(tr.p);
16450
16457
  return new Triple(
16451
16458
  keepFormulaBlanks && tr.s instanceof GraphTerm ? copyQuotedTerm(tr.s) : convertTerm(tr.s, true),
@@ -18,31 +18,31 @@
18
18
  {
19
19
  (?param {
20
20
  :Let :param ?param .
21
- } ("Huey" "Dewey" "Louie")) log:collectAllIn ?_b1 .
21
+ } ("Huey" "Dewey" "Louie")) log:collectAllIn ?eyeling_b1 .
22
22
  },
23
23
  {
24
24
  ((?param) {
25
25
  :Let :param ?param .
26
- } (("Huey") ("Dewey") ("Louie"))) log:collectAllIn ?_b1 .
26
+ } (("Huey") ("Dewey") ("Louie"))) log:collectAllIn ?eyeling_b1 .
27
27
  },
28
28
  {
29
29
  (?param {
30
30
  :Let :param ?param .
31
31
  ?param string:lessThan "Louie" .
32
- } ("Huey" "Dewey")) log:collectAllIn ?_b1 .
32
+ } ("Huey" "Dewey")) log:collectAllIn ?eyeling_b1 .
33
33
  }.
34
34
 
35
35
  {
36
36
  (?param {
37
37
  :Let :param ?param .
38
- } ("Huey" "Dewey" "Louie")) log:collectAllIn ?_b1 .
38
+ } ("Huey" "Dewey" "Louie")) log:collectAllIn ?eyeling_b1 .
39
39
  }
40
40
  pe:by [ pe:builtin log:collectAllIn ].
41
41
 
42
42
  {
43
43
  ((?param) {
44
44
  :Let :param ?param .
45
- } (("Huey") ("Dewey") ("Louie"))) log:collectAllIn ?_b1 .
45
+ } (("Huey") ("Dewey") ("Louie"))) log:collectAllIn ?eyeling_b1 .
46
46
  }
47
47
  pe:by [ pe:builtin log:collectAllIn ].
48
48
 
@@ -50,7 +50,7 @@
50
50
  (?param {
51
51
  :Let :param ?param .
52
52
  ?param string:lessThan "Louie" .
53
- } ("Huey" "Dewey")) log:collectAllIn ?_b1 .
53
+ } ("Huey" "Dewey")) log:collectAllIn ?eyeling_b1 .
54
54
  }
55
55
  pe:by [ pe:builtin log:collectAllIn ].
56
56
  }.
@@ -66,31 +66,31 @@
66
66
  {
67
67
  (?param {
68
68
  :Let :param ?param .
69
- } ("Huey" "Dewey" "Louie")) log:collectAllIn ?_b1 .
69
+ } ("Huey" "Dewey" "Louie")) log:collectAllIn ?eyeling_b1 .
70
70
  },
71
71
  {
72
72
  ((?param) {
73
73
  :Let :param ?param .
74
- } (("Huey") ("Dewey") ("Louie"))) log:collectAllIn ?_b1 .
74
+ } (("Huey") ("Dewey") ("Louie"))) log:collectAllIn ?eyeling_b1 .
75
75
  },
76
76
  {
77
77
  (?param {
78
78
  :Let :param ?param .
79
79
  ?param string:lessThan "Louie" .
80
- } ("Huey" "Dewey")) log:collectAllIn ?_b1 .
80
+ } ("Huey" "Dewey")) log:collectAllIn ?eyeling_b1 .
81
81
  }.
82
82
 
83
83
  {
84
84
  (?param {
85
85
  :Let :param ?param .
86
- } ("Huey" "Dewey" "Louie")) log:collectAllIn ?_b1 .
86
+ } ("Huey" "Dewey" "Louie")) log:collectAllIn ?eyeling_b1 .
87
87
  }
88
88
  pe:by [ pe:builtin log:collectAllIn ].
89
89
 
90
90
  {
91
91
  ((?param) {
92
92
  :Let :param ?param .
93
- } (("Huey") ("Dewey") ("Louie"))) log:collectAllIn ?_b1 .
93
+ } (("Huey") ("Dewey") ("Louie"))) log:collectAllIn ?eyeling_b1 .
94
94
  }
95
95
  pe:by [ pe:builtin log:collectAllIn ].
96
96
 
@@ -98,7 +98,7 @@
98
98
  (?param {
99
99
  :Let :param ?param .
100
100
  ?param string:lessThan "Louie" .
101
- } ("Huey" "Dewey")) log:collectAllIn ?_b1 .
101
+ } ("Huey" "Dewey")) log:collectAllIn ?eyeling_b1 .
102
102
  }
103
103
  pe:by [ pe:builtin log:collectAllIn ].
104
104
  }.
@@ -114,31 +114,31 @@
114
114
  {
115
115
  (?param {
116
116
  :Let :param ?param .
117
- } ("Huey" "Dewey" "Louie")) log:collectAllIn ?_b1 .
117
+ } ("Huey" "Dewey" "Louie")) log:collectAllIn ?eyeling_b1 .
118
118
  },
119
119
  {
120
120
  ((?param) {
121
121
  :Let :param ?param .
122
- } (("Huey") ("Dewey") ("Louie"))) log:collectAllIn ?_b1 .
122
+ } (("Huey") ("Dewey") ("Louie"))) log:collectAllIn ?eyeling_b1 .
123
123
  },
124
124
  {
125
125
  (?param {
126
126
  :Let :param ?param .
127
127
  ?param string:lessThan "Louie" .
128
- } ("Huey" "Dewey")) log:collectAllIn ?_b1 .
128
+ } ("Huey" "Dewey")) log:collectAllIn ?eyeling_b1 .
129
129
  }.
130
130
 
131
131
  {
132
132
  (?param {
133
133
  :Let :param ?param .
134
- } ("Huey" "Dewey" "Louie")) log:collectAllIn ?_b1 .
134
+ } ("Huey" "Dewey" "Louie")) log:collectAllIn ?eyeling_b1 .
135
135
  }
136
136
  pe:by [ pe:builtin log:collectAllIn ].
137
137
 
138
138
  {
139
139
  ((?param) {
140
140
  :Let :param ?param .
141
- } (("Huey") ("Dewey") ("Louie"))) log:collectAllIn ?_b1 .
141
+ } (("Huey") ("Dewey") ("Louie"))) log:collectAllIn ?eyeling_b1 .
142
142
  }
143
143
  pe:by [ pe:builtin log:collectAllIn ].
144
144
 
@@ -146,7 +146,7 @@
146
146
  (?param {
147
147
  :Let :param ?param .
148
148
  ?param string:lessThan "Louie" .
149
- } ("Huey" "Dewey")) log:collectAllIn ?_b1 .
149
+ } ("Huey" "Dewey")) log:collectAllIn ?eyeling_b1 .
150
150
  }
151
151
  pe:by [ pe:builtin log:collectAllIn ].
152
152
  }.
@@ -16,7 +16,7 @@
16
16
  :c :subTask ?s .
17
17
  } {
18
18
  ?s :state :Completed .
19
- }) log:forAllIn ?_b1 .
19
+ }) log:forAllIn ?eyeling_b1 .
20
20
  }.
21
21
 
22
22
  { :c a :CompositeTask . }
@@ -27,7 +27,7 @@
27
27
  :c :subTask ?s .
28
28
  } {
29
29
  ?s :state :Completed .
30
- }) log:forAllIn ?_b1 .
30
+ }) log:forAllIn ?eyeling_b1 .
31
31
  }
32
32
  pe:by [ pe:builtin log:forAllIn ].
33
33
  }.
package/eyeling.js CHANGED
@@ -16389,11 +16389,18 @@ function liftBlankRuleVars(premise, conclusion) {
16389
16389
  const mapping = Object.create(null);
16390
16390
  let counter = 0;
16391
16391
 
16392
+ // These variables are implementation details used to correlate one blank
16393
+ // node across the lifted rule body. Their names must not be spellable by
16394
+ // user input; otherwise a user variable such as ?_b1 can capture the
16395
+ // lifted blank node and leak it into the rule head. U+E000 is a private-use
16396
+ // code point and is not accepted by the lexer as part of a variable name.
16397
+ const INTERNAL_BLANK_VAR_PREFIX = '\uE000eyeling_b';
16398
+
16392
16399
  function blankToVar(label) {
16393
16400
  let name = mapping[label];
16394
16401
  if (name === undefined) {
16395
16402
  counter += 1;
16396
- name = `_b${counter}`;
16403
+ name = `${INTERNAL_BLANK_VAR_PREFIX}${counter}`;
16397
16404
  mapping[label] = name;
16398
16405
  }
16399
16406
  return new Var(name);
@@ -16445,7 +16452,7 @@ function liftBlankRuleVars(premise, conclusion) {
16445
16452
  // consumed by the builtin rather than ordinary triple patterns. Keep their
16446
16453
  // local blank nodes as Blank terms so the builtin can treat them as local
16447
16454
  // existentials, and bindings returned from an explicit scope are blank nodes
16448
- // instead of synthetic rule variables such as ?_b1.
16455
+ // instead of synthetic rule variables.
16449
16456
  const keepFormulaBlanks = isLogIncludesLikePredicate(tr.p);
16450
16457
  return new Triple(
16451
16458
  keepFormulaBlanks && tr.s instanceof GraphTerm ? copyQuotedTerm(tr.s) : convertTerm(tr.s, true),
package/lib/rules.js CHANGED
@@ -29,11 +29,18 @@ function liftBlankRuleVars(premise, conclusion) {
29
29
  const mapping = Object.create(null);
30
30
  let counter = 0;
31
31
 
32
+ // These variables are implementation details used to correlate one blank
33
+ // node across the lifted rule body. Their names must not be spellable by
34
+ // user input; otherwise a user variable such as ?_b1 can capture the
35
+ // lifted blank node and leak it into the rule head. U+E000 is a private-use
36
+ // code point and is not accepted by the lexer as part of a variable name.
37
+ const INTERNAL_BLANK_VAR_PREFIX = '\uE000eyeling_b';
38
+
32
39
  function blankToVar(label) {
33
40
  let name = mapping[label];
34
41
  if (name === undefined) {
35
42
  counter += 1;
36
- name = `_b${counter}`;
43
+ name = `${INTERNAL_BLANK_VAR_PREFIX}${counter}`;
37
44
  mapping[label] = name;
38
45
  }
39
46
  return new Var(name);
@@ -85,7 +92,7 @@ function liftBlankRuleVars(premise, conclusion) {
85
92
  // consumed by the builtin rather than ordinary triple patterns. Keep their
86
93
  // local blank nodes as Blank terms so the builtin can treat them as local
87
94
  // existentials, and bindings returned from an explicit scope are blank nodes
88
- // instead of synthetic rule variables such as ?_b1.
95
+ // instead of synthetic rule variables.
89
96
  const keepFormulaBlanks = isLogIncludesLikePredicate(tr.p);
90
97
  return new Triple(
91
98
  keepFormulaBlanks && tr.s instanceof GraphTerm ? copyQuotedTerm(tr.s) : convertTerm(tr.s, true),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.28.3",
3
+ "version": "1.28.4",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [
package/test/api.test.js CHANGED
@@ -3123,6 +3123,36 @@ MESSAGE
3123
3123
  ],
3124
3124
  },
3125
3125
 
3126
+
3127
+ {
3128
+ name: 'regression: user variable ?_b1 cannot capture lifted blank-node internals',
3129
+ opt: { proofComments: false },
3130
+ input: `@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
3131
+ @prefix : <http://example.org/> .
3132
+
3133
+ :test :value (6).
3134
+
3135
+ {
3136
+ :test :value [
3137
+ rdf:first 6;
3138
+ rdf:rest rdf:nil].
3139
+ }
3140
+ =>
3141
+ {
3142
+ ?_b1 a :test
3143
+ }.
3144
+
3145
+ {
3146
+ ?What a :test .
3147
+ } => { :test :is false }.
3148
+ `,
3149
+ // API output contains newly derived triples only; the input fact is not echoed.
3150
+ check(out) {
3151
+ assert.equal(out, '');
3152
+ },
3153
+ notExpect: [/\(6\)\s+a\s+:test\s*\./m, /:test\s+:is\s+false\s*\./m],
3154
+ },
3155
+
3126
3156
  {
3127
3157
  name: 'API empty input returns empty output',
3128
3158
  opt: { proofComments: false },