@muze-nl/od-jsontag 0.3.4 → 0.4.0
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.
- package/package.json +5 -3
- package/src/jsontag.mjs +30 -0
- package/src/parse.mjs +583 -996
- package/src/serialize.mjs +8 -9
package/src/parse.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import JSONTag from '@muze-nl/jsontag';
|
|
2
2
|
import Null from '@muze-nl/jsontag/src/lib/Null.mjs'
|
|
3
3
|
import serialize from './serialize.mjs'
|
|
4
|
-
import {source,isProxy,proxyType,getBuffer,getIndex,isChanged,isParsed,
|
|
4
|
+
import {source,isProxy,proxyType,getBuffer,getIndex,isChanged,isParsed,position,parent,resultSet} from './symbols.mjs'
|
|
5
5
|
|
|
6
|
-
const decoder = new TextDecoder()
|
|
7
6
|
const encoder = new TextEncoder()
|
|
8
|
-
const
|
|
7
|
+
const decoder = new TextDecoder()
|
|
9
8
|
|
|
10
|
-
function stringToSAB(strData)
|
|
9
|
+
function stringToSAB(strData)
|
|
10
|
+
{
|
|
11
11
|
const buffer = encoder.encode(strData)
|
|
12
12
|
const sab = new SharedArrayBuffer(buffer.length)
|
|
13
13
|
let uint8sab = new Uint8Array(sab)
|
|
@@ -15,7 +15,8 @@ function stringToSAB(strData) {
|
|
|
15
15
|
return uint8sab
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
function SABtoString(arr)
|
|
18
|
+
function SABtoString(arr)
|
|
19
|
+
{
|
|
19
20
|
let string = '';
|
|
20
21
|
for (let c of arr) {
|
|
21
22
|
string+= String.fromCharCode(c)
|
|
@@ -23,612 +24,421 @@ function SABtoString(arr) {
|
|
|
23
24
|
return string
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
class Slice
|
|
27
|
-
|
|
27
|
+
class Slice
|
|
28
|
+
{
|
|
29
|
+
constructor(start, end)
|
|
30
|
+
{
|
|
28
31
|
this.start = start;
|
|
29
32
|
this.end = end;
|
|
30
33
|
}
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
const isSlice = function(r)
|
|
36
|
+
const isSlice = function(r)
|
|
37
|
+
{
|
|
34
38
|
return r instanceof Slice
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
|
|
41
|
+
const resetObject = function(ob)
|
|
38
42
|
{
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
meta.unresolved = new Map()
|
|
44
|
-
}
|
|
45
|
-
if (!meta.baseURL) {
|
|
46
|
-
meta.baseURL = 'http://localhost/'
|
|
47
|
-
}
|
|
48
|
-
let at, ch, value, result;
|
|
49
|
-
let escapee = {
|
|
50
|
-
'"': '"',
|
|
51
|
-
"\\":"\\",
|
|
52
|
-
'/': '/',
|
|
53
|
-
b: "\b",
|
|
54
|
-
f: "\f",
|
|
55
|
-
n: "\n",
|
|
56
|
-
r: "\r",
|
|
57
|
-
t: "\t"
|
|
58
|
-
}
|
|
59
|
-
let offsetArray = []
|
|
60
|
-
if (!meta.resultArray) {
|
|
61
|
-
meta.resultArray = []
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
at = 0
|
|
65
|
-
ch = " "
|
|
66
|
-
|
|
67
|
-
let error = function(m)
|
|
68
|
-
{
|
|
69
|
-
let context
|
|
70
|
-
try {
|
|
71
|
-
context = decoder.decode(input.slice(at-100,at+100));
|
|
72
|
-
} catch(err) {}
|
|
73
|
-
throw {
|
|
74
|
-
name: 'SyntaxError',
|
|
75
|
-
message: m,
|
|
76
|
-
at: at,
|
|
77
|
-
input: context
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (typeof input == 'string' || input instanceof String) {
|
|
82
|
-
input = stringToSAB(input)
|
|
83
|
-
}
|
|
84
|
-
if (!(input instanceof Uint8Array)) {
|
|
85
|
-
error('parse only accepts Uint8Array or String as input')
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
let next = function(c)
|
|
89
|
-
{
|
|
90
|
-
if (c && c!==ch) {
|
|
91
|
-
let source = SABtoString(input)
|
|
92
|
-
error("Expected '"+c+"' instead of '"+ch+"': "+at+':'+source)
|
|
93
|
-
}
|
|
94
|
-
ch = String.fromCharCode(input.at(at))
|
|
95
|
-
at+=1
|
|
96
|
-
return ch
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
let number = function(tagName)
|
|
100
|
-
{
|
|
101
|
-
let numString = ''
|
|
102
|
-
if (ch==='-') {
|
|
103
|
-
numString = '-'
|
|
104
|
-
next('-')
|
|
105
|
-
}
|
|
106
|
-
while(ch>='0' && ch<='9') {
|
|
107
|
-
numString += ch
|
|
108
|
-
next()
|
|
109
|
-
}
|
|
110
|
-
if (ch==='.') {
|
|
111
|
-
numString+='.'
|
|
112
|
-
while(next() && ch >= '0' && ch <= '9') {
|
|
113
|
-
numString += ch
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
if (ch === 'e' || ch === 'E') {
|
|
117
|
-
numString += ch
|
|
118
|
-
next()
|
|
119
|
-
if (ch === '-' || ch === '+') {
|
|
120
|
-
numString += ch
|
|
121
|
-
next()
|
|
122
|
-
}
|
|
123
|
-
while (ch >= '0' && ch <= '9') {
|
|
124
|
-
numString += ch
|
|
125
|
-
next()
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
let result = new Number(numString).valueOf()
|
|
129
|
-
if (tagName) {
|
|
130
|
-
switch(tagName) {
|
|
131
|
-
case "int":
|
|
132
|
-
isInt(numString)
|
|
133
|
-
break
|
|
134
|
-
case "uint":
|
|
135
|
-
isInt(numString, [0,Infinity])
|
|
136
|
-
break
|
|
137
|
-
case "int8":
|
|
138
|
-
isInt(numString, [-128,127])
|
|
139
|
-
break
|
|
140
|
-
case "uint8":
|
|
141
|
-
isInt(numString, [0,255])
|
|
142
|
-
break
|
|
143
|
-
case "int16":
|
|
144
|
-
isInt(numString, [-32768,32767])
|
|
145
|
-
break
|
|
146
|
-
case "uint16":
|
|
147
|
-
isInt(numString, [0,65535])
|
|
148
|
-
break
|
|
149
|
-
case "int32":
|
|
150
|
-
isInt(numString, [-2147483648, 2147483647])
|
|
151
|
-
break
|
|
152
|
-
case "uint32":
|
|
153
|
-
isInt(numString, [0,4294967295])
|
|
154
|
-
break
|
|
155
|
-
case "timestamp":
|
|
156
|
-
case "int64":
|
|
157
|
-
isInt(numString, [-9223372036854775808,9223372036854775807])
|
|
158
|
-
break
|
|
159
|
-
case "uint64":
|
|
160
|
-
isInt(numString, [0,18446744073709551615])
|
|
161
|
-
break
|
|
162
|
-
case "float":
|
|
163
|
-
isFloat(numString)
|
|
164
|
-
break
|
|
165
|
-
case "float32":
|
|
166
|
-
isFloat(numString, [-3.4e+38,3.4e+38])
|
|
167
|
-
break
|
|
168
|
-
case "float64":
|
|
169
|
-
isFloat(numString, [-1.7e+308,+1.7e+308])
|
|
170
|
-
break
|
|
171
|
-
case "number":
|
|
172
|
-
//FIXME: what to check? should already be covered by JSON parsing rules?
|
|
173
|
-
break
|
|
174
|
-
default:
|
|
175
|
-
isTypeError(tagName, numString)
|
|
176
|
-
break
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
return result
|
|
43
|
+
delete ob[Symbol['JSONTag:Type']]
|
|
44
|
+
delete ob[Symbol['JSONTag:Attributes']]
|
|
45
|
+
for (let prop of Object.getOwnPropertyNames(ob)) {
|
|
46
|
+
delete ob[prop]
|
|
180
47
|
}
|
|
48
|
+
}
|
|
181
49
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
error('Syntax error, expected '+type+', got: '+value)
|
|
185
|
-
}
|
|
50
|
+
export default class Parser extends JSONTag.Parser
|
|
51
|
+
{
|
|
186
52
|
|
|
187
|
-
|
|
188
|
-
color: /^(rgb|hsl)a?\((\d+%?(deg|rad|grad|turn)?[,\s]+){2,3}[\s\/]*[\d\.]+%?\)$/i,
|
|
189
|
-
email: /^[A-Za-z0-9_!#$%&'*+\/=?`{|}~^.-]+@[A-Za-z0-9.-]+$/,
|
|
190
|
-
uuid: /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/,
|
|
191
|
-
decimal: /^\d*\.?\d*$/,
|
|
192
|
-
money: /^[A-Z]+\$\d*\.?\d*$/,
|
|
193
|
-
duration: /^(-?)P(?=\d|T\d)(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)([DW]))?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/,
|
|
194
|
-
phone: /^[+]?(?:\(\d+(?:\.\d+)?\)|\d+(?:\.\d+)?)(?:[ -]?(?:\(\d+(?:\.\d+)?\)|\d+(?:\.\d+)?))*(?:[ ]?(?:x|ext)\.?[ ]?\d{1,5})?$/,
|
|
195
|
-
time: /^(\d{2}):(\d{2})(?::(\d{2}(?:\.\d+)?))?$/,
|
|
196
|
-
date: /^-?[1-9][0-9]{3,}-([0][1-9]|[1][0-2])-([1-2][0-9]|[0][1-9]|[3][0-1])$/,
|
|
197
|
-
datetime: /^(\d{4,})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::(\d{2}(?:\.\d+)?))?$/,
|
|
198
|
-
range: /^\[-?(\d+\.)?\d+\,-?(\d+\.)?\d+\]$/
|
|
199
|
-
}
|
|
53
|
+
handlers
|
|
200
54
|
|
|
201
|
-
|
|
55
|
+
constructor(baseURL, immutable=true)
|
|
202
56
|
{
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
57
|
+
super(baseURL)
|
|
58
|
+
this.cachedProxies = new Map() //FIXME: set back to WeakMap
|
|
59
|
+
this.immutable = immutable
|
|
60
|
+
this.handlers = {
|
|
61
|
+
newArrayHandler: {
|
|
62
|
+
get: (target, prop) => {
|
|
63
|
+
if (target[prop] instanceof Function) {
|
|
64
|
+
return (...args) => {
|
|
65
|
+
args = args.map(arg => {
|
|
66
|
+
if (JSONTag.getType(arg)==='object' && !arg[isProxy]) {
|
|
67
|
+
arg = this.getNewValueProxy(arg)
|
|
68
|
+
}
|
|
69
|
+
return arg
|
|
70
|
+
})
|
|
71
|
+
return target[prop].apply(target, args)
|
|
72
|
+
}
|
|
73
|
+
} else if (prop===isChanged) {
|
|
74
|
+
return true
|
|
75
|
+
} else {
|
|
76
|
+
if (this.meta.access && !this.meta.access(target, prop)) {
|
|
77
|
+
return undefined
|
|
78
|
+
}
|
|
79
|
+
if (Array.isArray(target[prop])) {
|
|
80
|
+
return this.getArrayProxy(target[prop], target, this.handlers.newArrayHandler)
|
|
81
|
+
}
|
|
82
|
+
return target[prop]
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
set: (target, prop, value) => {
|
|
86
|
+
if (prop === isChanged || prop === parent) {
|
|
87
|
+
// prevent infinite loops, parent is only needed to mark it isChanged
|
|
88
|
+
// but this is a new array proxy, parent is already dirty
|
|
89
|
+
return true
|
|
90
|
+
}
|
|
91
|
+
if (this.meta.access && !this.meta.access(target, prop)) {
|
|
92
|
+
return undefined
|
|
93
|
+
}
|
|
94
|
+
if (JSONTag.getType(value)==='object' && !value[isProxy]) {
|
|
95
|
+
value = this.getNewValueProxy(value)
|
|
96
|
+
}
|
|
97
|
+
target[prop] = value
|
|
98
|
+
return true
|
|
217
99
|
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
100
|
+
},
|
|
101
|
+
newValueHandler: {
|
|
102
|
+
get: (target, prop) => {
|
|
103
|
+
switch(prop) {
|
|
104
|
+
case resultSet:
|
|
105
|
+
return this.meta.resultArray
|
|
106
|
+
break;
|
|
107
|
+
case source:
|
|
108
|
+
return target
|
|
109
|
+
break
|
|
110
|
+
case isProxy:
|
|
111
|
+
return true
|
|
112
|
+
break
|
|
113
|
+
case proxyType:
|
|
114
|
+
return 'new'
|
|
115
|
+
break
|
|
116
|
+
case getBuffer:
|
|
117
|
+
return (i) => {
|
|
118
|
+
let index = target[getIndex]
|
|
119
|
+
if (i != index) {
|
|
120
|
+
return encoder.encode('~'+index)
|
|
121
|
+
}
|
|
122
|
+
return serialize(target, {meta:this.meta, skipLength:true})
|
|
123
|
+
}
|
|
124
|
+
break
|
|
125
|
+
case getIndex:
|
|
126
|
+
return target[getIndex]
|
|
127
|
+
break
|
|
128
|
+
case isChanged:
|
|
129
|
+
return true
|
|
130
|
+
break
|
|
131
|
+
default:
|
|
132
|
+
if (this.meta.access && !this.meta.access(target, prop, 'get')) {
|
|
133
|
+
return undefined
|
|
134
|
+
}
|
|
135
|
+
if (Array.isArray(target[prop])) {
|
|
136
|
+
return this.getArrayProxy(target[prop], target, this.handlers.newArrayHandler)
|
|
137
|
+
}
|
|
138
|
+
return target[prop]
|
|
139
|
+
break
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
set: (target, prop, value) => {
|
|
143
|
+
if (this.meta.access && !this.meta.access(target, prop, 'set')) {
|
|
144
|
+
return undefined
|
|
145
|
+
}
|
|
146
|
+
if (JSONTag.getType(value)==='object' && !value[isProxy]) {
|
|
147
|
+
value = this.getNewValueProxy(value)
|
|
148
|
+
}
|
|
149
|
+
target[prop] = value
|
|
150
|
+
return true
|
|
233
151
|
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
152
|
+
},
|
|
153
|
+
arrayHandler: {
|
|
154
|
+
get: (target, prop, receiver) => {
|
|
155
|
+
const value = target?.[prop]
|
|
156
|
+
if (value instanceof Function) {
|
|
157
|
+
// if (['copyWithin','fill','pop','push','reverse','shift','sort','splice','unshift'].indexOf(prop)!==-1) {
|
|
158
|
+
// if (immutable) {
|
|
159
|
+
// throw new Error('dataspace is immutable')
|
|
160
|
+
// }
|
|
161
|
+
// }
|
|
162
|
+
return (...args) => {
|
|
163
|
+
args = args.map(arg => {
|
|
164
|
+
if (JSONTag.getType(arg)==='object' && !arg[isProxy]) {
|
|
165
|
+
arg = this.getNewValueProxy(arg)
|
|
166
|
+
}
|
|
167
|
+
return arg
|
|
168
|
+
})
|
|
169
|
+
return value.apply(receiver, args)
|
|
170
|
+
}
|
|
171
|
+
} else if (prop===isChanged) {
|
|
172
|
+
return target[isChanged] || target[parent][isChanged]
|
|
173
|
+
} else if (prop===source) {
|
|
174
|
+
return target
|
|
175
|
+
} else {
|
|
176
|
+
if (this.meta.access && !this.meta.access(target, prop, 'get')) {
|
|
177
|
+
return undefined
|
|
178
|
+
}
|
|
179
|
+
if (Array.isArray(value)) {
|
|
180
|
+
return this.getArrayProxy(value, target)
|
|
181
|
+
}
|
|
182
|
+
return value
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
set: (target, prop, value) => {
|
|
186
|
+
if (prop == parent) {
|
|
187
|
+
target[parent] = value
|
|
188
|
+
return true
|
|
189
|
+
}
|
|
190
|
+
if (this.immutable) {
|
|
191
|
+
throw new Error('dataspace is immutable')
|
|
192
|
+
}
|
|
193
|
+
if (this.meta.access && !this.meta.access(target, prop, 'set')) {
|
|
194
|
+
return undefined
|
|
195
|
+
}
|
|
196
|
+
if (JSONTag.getType(value)==='object' && !value[isProxy]) {
|
|
197
|
+
value = this.getNewValueProxy(value)
|
|
198
|
+
}
|
|
199
|
+
if (target[prop] === value) {
|
|
200
|
+
return true
|
|
201
|
+
}
|
|
202
|
+
target[prop] = value
|
|
203
|
+
target[isChanged] = true
|
|
204
|
+
target[parent][isChanged] = true
|
|
205
|
+
return true
|
|
206
|
+
},
|
|
207
|
+
deleteProperty: (target, prop) => {
|
|
208
|
+
if (this.immutable) {
|
|
209
|
+
throw new Error('dataspace is immutable')
|
|
210
|
+
}
|
|
211
|
+
if (this.meta.access && !this.meta.access(target, prop, 'deleteProperty')) {
|
|
212
|
+
return undefined
|
|
213
|
+
}
|
|
214
|
+
//FIXME: if target[prop] was the last reference to an object
|
|
215
|
+
//that object should be deleted so that its line will become empty
|
|
216
|
+
//when stringifying resultArray again
|
|
217
|
+
if (typeof target[prop] === 'undefined') {
|
|
218
|
+
return true
|
|
219
|
+
}
|
|
220
|
+
delete target[prop]
|
|
221
|
+
target[isChanged] = true
|
|
222
|
+
target[parent][isChanged] = true
|
|
223
|
+
return true
|
|
238
224
|
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
let isDuration = function(duration)
|
|
307
|
-
{
|
|
308
|
-
let result = regexes.duration.test(duration)
|
|
309
|
-
if (!result) {
|
|
310
|
-
isTypeError('duration',duration)
|
|
311
|
-
}
|
|
312
|
-
return true
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
let isPhone = function(phone)
|
|
316
|
-
{
|
|
317
|
-
let result = regexes.phone.test(phone)
|
|
318
|
-
if (!result) {
|
|
319
|
-
isTypeError('phone',phone)
|
|
320
|
-
}
|
|
321
|
-
return true
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
let isRange = function(range)
|
|
325
|
-
{
|
|
326
|
-
let result = regexes.range.test(range)
|
|
327
|
-
if (!result) {
|
|
328
|
-
isTypeError('range',range)
|
|
329
|
-
}
|
|
330
|
-
return true
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
let isTime = function(time)
|
|
334
|
-
{
|
|
335
|
-
let result = regexes.time.test(time)
|
|
336
|
-
if (!result) {
|
|
337
|
-
isTypeError('time',time)
|
|
338
|
-
}
|
|
339
|
-
return true
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
let isDate = function(date)
|
|
343
|
-
{
|
|
344
|
-
let result = regexes.date.test(date)
|
|
345
|
-
if (!result) {
|
|
346
|
-
isTypeError('date',date)
|
|
347
|
-
}
|
|
348
|
-
return true
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
let isDatetime = function(datetime)
|
|
352
|
-
{
|
|
353
|
-
let result = regexes.datetime.test(datetime)
|
|
354
|
-
if (!result) {
|
|
355
|
-
isTypeError('datetime',datetime)
|
|
356
|
-
}
|
|
357
|
-
return true
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
let checkStringType = function(tagName, value)
|
|
361
|
-
{
|
|
362
|
-
if (!tagName) {
|
|
363
|
-
return
|
|
364
|
-
}
|
|
365
|
-
switch(tagName){
|
|
366
|
-
case "object":
|
|
367
|
-
case "array":
|
|
368
|
-
case "int8":
|
|
369
|
-
case "uint8":
|
|
370
|
-
case "int16":
|
|
371
|
-
case "uint16":
|
|
372
|
-
case "int32":
|
|
373
|
-
case "uint32":
|
|
374
|
-
case "int64":
|
|
375
|
-
case "uint64":
|
|
376
|
-
case "int":
|
|
377
|
-
case "uint":
|
|
378
|
-
case "float32":
|
|
379
|
-
case "float64":
|
|
380
|
-
case "float":
|
|
381
|
-
case "timestamp":
|
|
382
|
-
isTypeError(tagName, value)
|
|
383
|
-
break
|
|
384
|
-
case "uuid":
|
|
385
|
-
return isUuid(value)
|
|
386
|
-
case "decimal":
|
|
387
|
-
return isDecimal(value)
|
|
388
|
-
case "money":
|
|
389
|
-
return isMoney(value)
|
|
390
|
-
case "url":
|
|
391
|
-
return isUrl(value)
|
|
392
|
-
case "link":
|
|
393
|
-
case "string":
|
|
394
|
-
case "text":
|
|
395
|
-
case "blob":
|
|
396
|
-
case "hash":
|
|
397
|
-
//anything goes
|
|
398
|
-
return true
|
|
399
|
-
case "color":
|
|
400
|
-
return isColor(value)
|
|
401
|
-
case "email":
|
|
402
|
-
return isEmail(value)
|
|
403
|
-
case "duration":
|
|
404
|
-
return isDuration(value)
|
|
405
|
-
case "phone":
|
|
406
|
-
return isPhone(value)
|
|
407
|
-
case "range":
|
|
408
|
-
return isRange(value)
|
|
409
|
-
case "time":
|
|
410
|
-
return isTime(value)
|
|
411
|
-
case "date":
|
|
412
|
-
return isDate(value)
|
|
413
|
-
case "datetime":
|
|
414
|
-
return isDatetime(value)
|
|
415
|
-
}
|
|
416
|
-
error('Syntax error: unknown tagName '+tagName)
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
let string = function(tagName)
|
|
420
|
-
{
|
|
421
|
-
let value = [], hex, i, uffff;
|
|
422
|
-
if (ch !== '"') {
|
|
423
|
-
error("Syntax Error")
|
|
424
|
-
}
|
|
425
|
-
next('"')
|
|
426
|
-
while(ch) {
|
|
427
|
-
if (ch==='"') {
|
|
428
|
-
next()
|
|
429
|
-
let bytes = new Uint8Array(value)
|
|
430
|
-
value = decoder.decode(bytes)
|
|
431
|
-
checkStringType(tagName, value)
|
|
432
|
-
return value
|
|
433
|
-
}
|
|
434
|
-
if (ch==='\\') {
|
|
435
|
-
next()
|
|
436
|
-
if (ch==='u') {
|
|
437
|
-
for (i=0; i<4; i++) {
|
|
438
|
-
hex = parseInt(next(), 16)
|
|
439
|
-
if (!isFinite(hex)) {
|
|
225
|
+
},
|
|
226
|
+
defaultHandler: {
|
|
227
|
+
get: (target, prop, receiver) => {
|
|
228
|
+
switch(prop) {
|
|
229
|
+
case resultSet:
|
|
230
|
+
return this.meta.resultArray
|
|
231
|
+
break;
|
|
232
|
+
case isProxy:
|
|
233
|
+
return true
|
|
234
|
+
break
|
|
235
|
+
case proxyType:
|
|
236
|
+
return 'parse'
|
|
237
|
+
break
|
|
238
|
+
case getBuffer:
|
|
239
|
+
return (i) => {
|
|
240
|
+
let index = target[getIndex]
|
|
241
|
+
if (i != index) {
|
|
242
|
+
return encoder.encode('~'+index)
|
|
243
|
+
}
|
|
244
|
+
if (target[isChanged]) {
|
|
245
|
+
return serialize(target, {skipLength: true})
|
|
246
|
+
}
|
|
247
|
+
return target[position].input.slice(target[position].start,target[position].end)
|
|
248
|
+
}
|
|
249
|
+
break
|
|
250
|
+
case getIndex:
|
|
251
|
+
return target[getIndex]
|
|
252
|
+
break
|
|
253
|
+
case isChanged:
|
|
254
|
+
return target[isChanged]
|
|
255
|
+
break
|
|
256
|
+
}
|
|
257
|
+
this.firstParse(target, receiver)
|
|
258
|
+
switch(prop) {
|
|
259
|
+
case source:
|
|
260
|
+
if (this.meta.access && !this.meta.access(target, prop, 'get')) {
|
|
261
|
+
return undefined
|
|
262
|
+
}
|
|
263
|
+
return target
|
|
264
|
+
break
|
|
265
|
+
default:
|
|
266
|
+
if (this.meta.access && !this.meta.access(target, prop, 'get')) {
|
|
267
|
+
return undefined
|
|
268
|
+
}
|
|
269
|
+
if (Array.isArray(target[prop])) {
|
|
270
|
+
return this.getArrayProxy(target[prop], target)
|
|
271
|
+
}
|
|
272
|
+
return target[prop]
|
|
273
|
+
break
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
set: (target, prop, value, receiver) => {
|
|
277
|
+
if (this.immutable && prop!==resultSet && prop!==source && prop!==isChanged) {
|
|
278
|
+
throw new Error('dataspace is immutable')
|
|
279
|
+
}
|
|
280
|
+
switch(prop) {
|
|
281
|
+
case isChanged:
|
|
282
|
+
break
|
|
283
|
+
case source:
|
|
284
|
+
resetObject(target)
|
|
285
|
+
target[position] = value[position]
|
|
286
|
+
target[isParsed] = false
|
|
287
|
+
target[isChanged] = false
|
|
288
|
+
return true
|
|
289
|
+
break
|
|
290
|
+
case resultSet:
|
|
440
291
|
break
|
|
441
|
-
}
|
|
442
|
-
uffff = uffff * 16 + hex
|
|
443
292
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
293
|
+
this.firstParse(target, receiver)
|
|
294
|
+
if (this.meta.access && !this.meta.access(target, prop, 'set')) {
|
|
295
|
+
return undefined
|
|
296
|
+
}
|
|
297
|
+
if (value && JSONTag.getType(value)==='object' && !value[isProxy]) {
|
|
298
|
+
value = this.getNewValueProxy(value)
|
|
299
|
+
}
|
|
300
|
+
if (target[prop] === value) {
|
|
301
|
+
return true
|
|
302
|
+
}
|
|
303
|
+
target[prop] = value
|
|
304
|
+
target[isChanged] = true
|
|
305
|
+
return true
|
|
306
|
+
},
|
|
307
|
+
deleteProperty: (target, prop) => {
|
|
308
|
+
if (this.immutable) {
|
|
309
|
+
throw new Error('dataspace is immutable')
|
|
310
|
+
}
|
|
311
|
+
if (this.meta.access && !this.meta.access(target, prop, 'deleteProperty')) {
|
|
312
|
+
return undefined
|
|
313
|
+
}
|
|
314
|
+
this.firstParse(target)
|
|
315
|
+
if (typeof target[prop] === 'undefined') {
|
|
316
|
+
return true
|
|
317
|
+
}
|
|
318
|
+
delete target[prop]
|
|
319
|
+
target[isChanged] = true
|
|
320
|
+
return true
|
|
321
|
+
},
|
|
322
|
+
ownKeys: (target) => {
|
|
323
|
+
this.firstParse(target)
|
|
324
|
+
return Reflect.ownKeys(target)
|
|
325
|
+
},
|
|
326
|
+
getOwnPropertyDescriptor: (target, prop) => {
|
|
327
|
+
this.firstParse(target)
|
|
328
|
+
return Reflect.getOwnPropertyDescriptor(target, prop)
|
|
329
|
+
},
|
|
330
|
+
defineProperty: (target, prop, descriptor) => {
|
|
331
|
+
if (this.immutable) {
|
|
332
|
+
throw new Error('dataspace is immutable')
|
|
333
|
+
}
|
|
334
|
+
if (this.meta.access && !this.meta.access(target, prop, 'defineProperty')) {
|
|
335
|
+
return undefined
|
|
336
|
+
}
|
|
337
|
+
this.firstParse(target)
|
|
338
|
+
target[isChanged] = true
|
|
339
|
+
return Object.defineProperty(target, prop, descriptor)
|
|
340
|
+
},
|
|
341
|
+
has: (target, prop) => {
|
|
342
|
+
if (this.meta.access && !this.meta.access(target, prop, 'has')) {
|
|
343
|
+
return false
|
|
344
|
+
}
|
|
345
|
+
this.firstParse()
|
|
346
|
+
return prop in target
|
|
347
|
+
},
|
|
348
|
+
setPrototypeOf: () => {
|
|
349
|
+
throw new Error('changing prototypes is not supported')
|
|
453
350
|
}
|
|
454
|
-
} else {
|
|
455
|
-
value.push(ch.charCodeAt(0))
|
|
456
|
-
next()
|
|
457
351
|
}
|
|
458
352
|
}
|
|
459
|
-
error("Syntax error: incomplete string")
|
|
460
353
|
}
|
|
461
354
|
|
|
462
|
-
|
|
355
|
+
next(c)
|
|
463
356
|
{
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
if (ch !== '<') {
|
|
468
|
-
error("Syntax Error")
|
|
469
|
-
}
|
|
470
|
-
next('<')
|
|
471
|
-
key = word()
|
|
472
|
-
if (!key) {
|
|
473
|
-
error('Syntax Error: expected tag name')
|
|
474
|
-
}
|
|
475
|
-
tagOb.tagName = key
|
|
476
|
-
whitespace()
|
|
477
|
-
while(ch) {
|
|
478
|
-
if (ch==='>') {
|
|
479
|
-
next('>')
|
|
480
|
-
return tagOb
|
|
481
|
-
}
|
|
482
|
-
key = word()
|
|
483
|
-
if (!key) {
|
|
484
|
-
error('Syntax Error: expected attribute name')
|
|
485
|
-
}
|
|
486
|
-
whitespace()
|
|
487
|
-
next('=')
|
|
488
|
-
whitespace()
|
|
489
|
-
val = string()
|
|
490
|
-
tagOb.attributes[key] = val
|
|
491
|
-
whitespace()
|
|
492
|
-
}
|
|
493
|
-
error('Syntax Error: unexpected end of input')
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
let whitespace = function()
|
|
497
|
-
{
|
|
498
|
-
while (ch) {
|
|
499
|
-
switch(ch) {
|
|
500
|
-
case ' ':
|
|
501
|
-
case "\t":
|
|
502
|
-
case "\r":
|
|
503
|
-
case "\n":
|
|
504
|
-
next()
|
|
505
|
-
break
|
|
506
|
-
default:
|
|
507
|
-
return
|
|
508
|
-
break
|
|
509
|
-
}
|
|
357
|
+
if (c && c!==this.ch) {
|
|
358
|
+
let source = SABtoString(this.input)
|
|
359
|
+
this.error("Expected '"+c+"' instead of '"+this.ch+"':"+this.at+':'+source)
|
|
510
360
|
}
|
|
361
|
+
this.ch = String.fromCharCode(this.input.at(this.at))
|
|
362
|
+
this.at+=1
|
|
363
|
+
return this.ch
|
|
511
364
|
}
|
|
512
365
|
|
|
513
|
-
|
|
366
|
+
error(m)
|
|
514
367
|
{
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
next()
|
|
520
|
-
} else {
|
|
521
|
-
error('Syntax Error: expected word')
|
|
522
|
-
}
|
|
523
|
-
while((ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9') || ch=='_') {
|
|
524
|
-
val += ch
|
|
525
|
-
next()
|
|
526
|
-
}
|
|
527
|
-
return val
|
|
528
|
-
}
|
|
368
|
+
let context
|
|
369
|
+
try {
|
|
370
|
+
context = decoder.decode(this.input.slice(this.at,this.at+100));
|
|
371
|
+
} catch(e) {
|
|
529
372
|
|
|
530
|
-
let boolOrNull = function(tagName)
|
|
531
|
-
{
|
|
532
|
-
let w = word()
|
|
533
|
-
if (!w || typeof w !== 'string') {
|
|
534
|
-
error('Syntax error: expected boolean or null, got "'+w+'"')
|
|
535
373
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
return true
|
|
542
|
-
break
|
|
543
|
-
case 'false':
|
|
544
|
-
if (tagName && tagName!=='boolean') {
|
|
545
|
-
isTypeError(tagName,w)
|
|
546
|
-
}
|
|
547
|
-
return false
|
|
548
|
-
break
|
|
549
|
-
case 'null':
|
|
550
|
-
return null
|
|
551
|
-
break
|
|
552
|
-
default:
|
|
553
|
-
error('Syntax error: expected boolean or null, got "'+w+'"')
|
|
554
|
-
break
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
let checkUnresolved = function(item, object, key)
|
|
559
|
-
{
|
|
560
|
-
if (JSONTag.getType(item)==='link') {
|
|
561
|
-
let link = ''+item
|
|
562
|
-
let links = meta.unresolved.get(link)
|
|
563
|
-
if (typeof links === 'undefined') {
|
|
564
|
-
meta.unresolved.set(link,[])
|
|
565
|
-
links = meta.unresolved.get(link)
|
|
566
|
-
}
|
|
567
|
-
let count = links.push({
|
|
568
|
-
src: new WeakRef(object),
|
|
569
|
-
key: key
|
|
570
|
-
})
|
|
374
|
+
throw {
|
|
375
|
+
name: 'SyntaxError',
|
|
376
|
+
message: m,
|
|
377
|
+
at: this.at,
|
|
378
|
+
input: context
|
|
571
379
|
}
|
|
572
380
|
}
|
|
573
381
|
|
|
574
|
-
|
|
382
|
+
array()
|
|
575
383
|
{
|
|
576
384
|
let item, array = []
|
|
577
|
-
if (ch !== '[') {
|
|
578
|
-
error("Syntax error")
|
|
385
|
+
if (this.ch !== '[') {
|
|
386
|
+
this.error("Syntax error")
|
|
579
387
|
}
|
|
580
|
-
next('[')
|
|
581
|
-
whitespace()
|
|
582
|
-
if (ch===']') {
|
|
583
|
-
next(']')
|
|
388
|
+
this.next('[')
|
|
389
|
+
this.whitespace()
|
|
390
|
+
if (this.ch===']') {
|
|
391
|
+
this.next(']')
|
|
584
392
|
return array
|
|
585
393
|
}
|
|
586
|
-
while(ch) {
|
|
587
|
-
item = value()
|
|
588
|
-
checkUnresolved(item, array, array.length)
|
|
394
|
+
while(this.ch) {
|
|
395
|
+
item = this.value()
|
|
396
|
+
this.checkUnresolved(item, array, array.length)
|
|
589
397
|
if (isSlice(item)) {
|
|
590
|
-
array = array.concat(meta.resultArray.slice(item.start, item.end))
|
|
398
|
+
array = array.concat(this.meta.resultArray.slice(item.start, item.end))
|
|
591
399
|
} else {
|
|
592
400
|
array.push(item)
|
|
593
401
|
}
|
|
594
|
-
whitespace()
|
|
595
|
-
if (ch===']') {
|
|
596
|
-
next(']')
|
|
402
|
+
this.whitespace()
|
|
403
|
+
if (this.ch===']') {
|
|
404
|
+
this.next(']')
|
|
597
405
|
return array
|
|
598
406
|
}
|
|
599
|
-
next(',')
|
|
600
|
-
whitespace()
|
|
407
|
+
this.next(',')
|
|
408
|
+
this.whitespace()
|
|
601
409
|
}
|
|
602
|
-
error("Input stopped early")
|
|
410
|
+
this.error("Input stopped early")
|
|
603
411
|
}
|
|
604
412
|
|
|
605
|
-
|
|
413
|
+
|
|
414
|
+
object(object={})
|
|
606
415
|
{
|
|
607
416
|
let key, val
|
|
608
|
-
if (ch !== '{') {
|
|
609
|
-
error("Syntax Error")
|
|
610
|
-
}
|
|
611
|
-
next('{')
|
|
612
|
-
whitespace()
|
|
613
|
-
|
|
614
|
-
|
|
417
|
+
if (this.ch !== '{') {
|
|
418
|
+
this.error("Syntax Error")
|
|
419
|
+
}
|
|
420
|
+
this.next('{')
|
|
421
|
+
this.whitespace()
|
|
422
|
+
resetObject(object)
|
|
423
|
+
if (this.ch==='}') {
|
|
424
|
+
this.next('}')
|
|
615
425
|
return object
|
|
616
426
|
}
|
|
617
427
|
let enumerable = true
|
|
618
|
-
while(ch) {
|
|
619
|
-
if (ch==='#') {
|
|
428
|
+
while(this.ch) {
|
|
429
|
+
if (this.ch==='#') {
|
|
620
430
|
enumerable = false
|
|
621
|
-
next()
|
|
431
|
+
this.next()
|
|
622
432
|
} else {
|
|
623
433
|
enumerable = true
|
|
624
434
|
}
|
|
625
|
-
key = string()
|
|
435
|
+
key = this.string()
|
|
626
436
|
if (key==='__proto__') {
|
|
627
|
-
error("Attempt at prototype pollution")
|
|
437
|
+
this.error("Attempt at prototype pollution")
|
|
628
438
|
}
|
|
629
|
-
whitespace()
|
|
630
|
-
next(':')
|
|
631
|
-
val = value()
|
|
439
|
+
this.whitespace()
|
|
440
|
+
this.next(':')
|
|
441
|
+
val = this.value()
|
|
632
442
|
if (!enumerable) {
|
|
633
443
|
Object.defineProperty(object, key, {
|
|
634
444
|
configurable: true, //important, must be true, otherwise Proxies cannot use it
|
|
@@ -639,479 +449,158 @@ export default function parse(input, meta, immutable=true)
|
|
|
639
449
|
} else {
|
|
640
450
|
object[key] = val
|
|
641
451
|
}
|
|
642
|
-
checkUnresolved(val, object, key)
|
|
643
|
-
whitespace()
|
|
644
|
-
if (ch==='}') {
|
|
645
|
-
next('}')
|
|
452
|
+
this.checkUnresolved(val, object, key)
|
|
453
|
+
this.whitespace()
|
|
454
|
+
if (this.ch==='}') {
|
|
455
|
+
this.next('}')
|
|
646
456
|
return object
|
|
647
457
|
}
|
|
648
|
-
next(',')
|
|
649
|
-
whitespace()
|
|
458
|
+
this.next(',')
|
|
459
|
+
this.whitespace()
|
|
650
460
|
}
|
|
651
|
-
error("Input stopped early")
|
|
461
|
+
this.error("Input stopped early")
|
|
652
462
|
}
|
|
653
463
|
|
|
654
|
-
|
|
464
|
+
string(tagName)
|
|
655
465
|
{
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
while(ch>='0' && ch<='9') {
|
|
660
|
-
numString += ch
|
|
661
|
-
next()
|
|
662
|
-
}
|
|
663
|
-
if (ch!==')') {
|
|
664
|
-
error('Syntax error: not a length')
|
|
665
|
-
}
|
|
666
|
-
next()
|
|
667
|
-
return parseInt(numString)
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
let offset = function()
|
|
671
|
-
{
|
|
672
|
-
next('~')
|
|
673
|
-
let numString = ''
|
|
674
|
-
while(ch>='0' && ch<='9') {
|
|
675
|
-
numString += ch
|
|
676
|
-
next()
|
|
677
|
-
}
|
|
678
|
-
if (ch=='-') {
|
|
679
|
-
next('-')
|
|
680
|
-
let endString = ''
|
|
681
|
-
while(ch>='0' && ch<='9') {
|
|
682
|
-
endString += ch
|
|
683
|
-
next()
|
|
684
|
-
}
|
|
685
|
-
return new Slice(parseInt(numString),parseInt(endString)+1) // +1 because array.slice(start,end) slices upto but not including end
|
|
686
|
-
}
|
|
687
|
-
return parseInt(numString)
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
let parseValue = function(position, ob={}) {
|
|
691
|
-
input = position.input
|
|
692
|
-
at = position.start
|
|
693
|
-
next()
|
|
694
|
-
return value(ob)
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
const makeChildProxies = function(parent) {
|
|
698
|
-
Object.entries(parent).forEach(([key,entry]) => {
|
|
699
|
-
if (Array.isArray(entry)) {
|
|
700
|
-
makeChildProxies(entry)
|
|
701
|
-
} else if (entry && JSONTag.getType(entry)==='object') {
|
|
702
|
-
if (entry[isProxy]) {
|
|
703
|
-
// do nothing
|
|
704
|
-
} else {
|
|
705
|
-
parent[key] = getNewValueProxy(entry)
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
})
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
const getArrayProxy = (arr, par, handler) => {
|
|
712
|
-
if (!handler) {
|
|
713
|
-
handler = handlers.arrayHandler
|
|
714
|
-
}
|
|
715
|
-
if (!arrayProxies.has(arr)) {
|
|
716
|
-
arrayProxies.set(arr, new Proxy(arr, handler))
|
|
466
|
+
let value = [], hex, i, uffff;
|
|
467
|
+
if (this.ch !== '"') {
|
|
468
|
+
this.error("Syntax Error")
|
|
717
469
|
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
if (target[prop] instanceof Function) {
|
|
727
|
-
return (...args) => {
|
|
728
|
-
args = args.map(arg => {
|
|
729
|
-
if (JSONTag.getType(arg)==='object' && !arg[isProxy]) {
|
|
730
|
-
arg = getNewValueProxy(arg)
|
|
731
|
-
}
|
|
732
|
-
return arg
|
|
733
|
-
})
|
|
734
|
-
return target[prop].apply(target, args)
|
|
735
|
-
}
|
|
736
|
-
} else if (prop===isChanged) {
|
|
737
|
-
return true
|
|
738
|
-
} else {
|
|
739
|
-
if (meta.access && !meta.access(target, prop)) {
|
|
740
|
-
return undefined
|
|
741
|
-
}
|
|
742
|
-
if (Array.isArray(target[prop])) {
|
|
743
|
-
return getArrayProxy(target[prop], target, handlers.newArrayHandler)
|
|
744
|
-
}
|
|
745
|
-
return target[prop]
|
|
746
|
-
}
|
|
747
|
-
},
|
|
748
|
-
set(target, prop, value) {
|
|
749
|
-
if (prop === isChanged || prop === parent) {
|
|
750
|
-
// prevent infinite loops, parent is only needed to mark it isChanged
|
|
751
|
-
// but this is a new array proxy, parent is already dirty
|
|
752
|
-
return true
|
|
753
|
-
}
|
|
754
|
-
if (meta.access && !meta.access(target, prop)) {
|
|
755
|
-
return undefined
|
|
756
|
-
}
|
|
757
|
-
if (JSONTag.getType(value)==='object' && !value[isProxy]) {
|
|
758
|
-
value = getNewValueProxy(value)
|
|
759
|
-
}
|
|
760
|
-
target[prop] = value
|
|
761
|
-
return true
|
|
470
|
+
this.next('"')
|
|
471
|
+
while(this.ch) {
|
|
472
|
+
if (this.ch==='"') {
|
|
473
|
+
this.next()
|
|
474
|
+
let bytes = new Uint8Array(value)
|
|
475
|
+
value = decoder.decode(bytes)
|
|
476
|
+
this.checkStringType(tagName, value)
|
|
477
|
+
return value
|
|
762
478
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
case source:
|
|
771
|
-
return target
|
|
772
|
-
break
|
|
773
|
-
case isProxy:
|
|
774
|
-
return true
|
|
775
|
-
break
|
|
776
|
-
case proxyType:
|
|
777
|
-
return 'new'
|
|
778
|
-
break
|
|
779
|
-
case getBuffer:
|
|
780
|
-
return (i) => {
|
|
781
|
-
let index = target[getIndex]
|
|
782
|
-
if (i != index) {
|
|
783
|
-
return encoder.encode('~'+index)
|
|
784
|
-
}
|
|
785
|
-
return serialize(target, {meta, skipLength:true})
|
|
786
|
-
}
|
|
787
|
-
break
|
|
788
|
-
case getIndex:
|
|
789
|
-
return target[getIndex]
|
|
790
|
-
break
|
|
791
|
-
case isChanged:
|
|
792
|
-
return true
|
|
793
|
-
break
|
|
794
|
-
default:
|
|
795
|
-
if (meta.access && !meta.access(target, prop, 'get')) {
|
|
796
|
-
return undefined
|
|
797
|
-
}
|
|
798
|
-
if (Array.isArray(target[prop])) {
|
|
799
|
-
return getArrayProxy(target[prop], target, handlers.newArrayHandler)
|
|
479
|
+
if (this.ch==='\\') {
|
|
480
|
+
this.next()
|
|
481
|
+
if (this.ch==='u') {
|
|
482
|
+
for (i=0; i<4; i++) {
|
|
483
|
+
hex = parseInt(this.next(), 16)
|
|
484
|
+
if (!this.isFinite(hex)) {
|
|
485
|
+
break
|
|
800
486
|
}
|
|
801
|
-
|
|
802
|
-
break
|
|
803
|
-
}
|
|
804
|
-
},
|
|
805
|
-
set(target, prop, value) {
|
|
806
|
-
if (meta.access && !meta.access(target, prop, 'set')) {
|
|
807
|
-
return undefined
|
|
808
|
-
}
|
|
809
|
-
if (JSONTag.getType(value)==='object' && !value[isProxy]) {
|
|
810
|
-
value = getNewValueProxy(value)
|
|
811
|
-
}
|
|
812
|
-
target[prop] = value
|
|
813
|
-
return true
|
|
814
|
-
}
|
|
815
|
-
},
|
|
816
|
-
arrayHandler: {
|
|
817
|
-
get(target, prop, receiver) {
|
|
818
|
-
const value = target?.[prop]
|
|
819
|
-
if (value instanceof Function) {
|
|
820
|
-
// if (['copyWithin','fill','pop','push','reverse','shift','sort','splice','unshift'].indexOf(prop)!==-1) {
|
|
821
|
-
// if (immutable) {
|
|
822
|
-
// throw new Error('dataspace is immutable')
|
|
823
|
-
// }
|
|
824
|
-
// }
|
|
825
|
-
return (...args) => {
|
|
826
|
-
args = args.map(arg => {
|
|
827
|
-
if (JSONTag.getType(arg)==='object' && !arg[isProxy]) {
|
|
828
|
-
arg = getNewValueProxy(arg)
|
|
829
|
-
}
|
|
830
|
-
return arg
|
|
831
|
-
})
|
|
832
|
-
return value.apply(receiver, args)
|
|
487
|
+
uffff = uffff * 16 + hex
|
|
833
488
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
489
|
+
let str = String.fromCharCode(uffff)
|
|
490
|
+
let bytes = encoder.encode(str)
|
|
491
|
+
value.push.apply(value, bytes)
|
|
492
|
+
this.next()
|
|
493
|
+
} else if (typeof this.escapee[this.ch] === 'string') {
|
|
494
|
+
value.push(this.escapee[this.ch].charCodeAt(0))
|
|
495
|
+
this.next()
|
|
838
496
|
} else {
|
|
839
|
-
if (meta.access && !meta.access(target, prop, 'get')) {
|
|
840
|
-
return undefined
|
|
841
|
-
}
|
|
842
|
-
if (Array.isArray(value)) {
|
|
843
|
-
return getArrayProxy(value, target)
|
|
844
|
-
}
|
|
845
|
-
return value
|
|
846
|
-
}
|
|
847
|
-
},
|
|
848
|
-
set(target, prop, value) {
|
|
849
|
-
if (prop == parent) {
|
|
850
|
-
target[parent] = value
|
|
851
|
-
return true
|
|
852
|
-
}
|
|
853
|
-
if (immutable) {
|
|
854
|
-
throw new Error('dataspace is immutable')
|
|
855
|
-
}
|
|
856
|
-
if (meta.access && !meta.access(target, prop, 'set')) {
|
|
857
|
-
return undefined
|
|
858
|
-
}
|
|
859
|
-
if (JSONTag.getType(value)==='object' && !value[isProxy]) {
|
|
860
|
-
value = getNewValueProxy(value)
|
|
861
|
-
}
|
|
862
|
-
if (target[prop] === value) {
|
|
863
|
-
return true
|
|
864
|
-
}
|
|
865
|
-
target[prop] = value
|
|
866
|
-
target[isChanged] = true
|
|
867
|
-
target[parent][isChanged] = true
|
|
868
|
-
return true
|
|
869
|
-
},
|
|
870
|
-
deleteProperty(target, prop) {
|
|
871
|
-
if (immutable) {
|
|
872
|
-
throw new Error('dataspace is immutable')
|
|
873
|
-
}
|
|
874
|
-
if (meta.access && !meta.access(target, prop, 'deleteProperty')) {
|
|
875
|
-
return undefined
|
|
876
|
-
}
|
|
877
|
-
//FIXME: if target[prop] was the last reference to an object
|
|
878
|
-
//that object should be deleted so that its line will become empty
|
|
879
|
-
//when stringifying resultArray again
|
|
880
|
-
if (typeof target[prop] === 'undefined') {
|
|
881
|
-
return true
|
|
882
|
-
}
|
|
883
|
-
delete target[prop]
|
|
884
|
-
target[isChanged] = true
|
|
885
|
-
target[parent][isChanged] = true
|
|
886
|
-
return true
|
|
887
|
-
}
|
|
888
|
-
},
|
|
889
|
-
handler: {
|
|
890
|
-
get(target, prop, receiver) {
|
|
891
|
-
switch(prop) {
|
|
892
|
-
case resultSet:
|
|
893
|
-
return meta.resultArray
|
|
894
|
-
break;
|
|
895
|
-
case isProxy:
|
|
896
|
-
return true
|
|
897
|
-
break
|
|
898
|
-
case proxyType:
|
|
899
|
-
return 'parse'
|
|
900
|
-
break
|
|
901
|
-
case getBuffer:
|
|
902
|
-
return (i) => {
|
|
903
|
-
let index = target[getIndex]
|
|
904
|
-
if (i != index) {
|
|
905
|
-
return encoder.encode('~'+index)
|
|
906
|
-
}
|
|
907
|
-
if (target[isChanged]) {
|
|
908
|
-
return serialize(target, {skipLength: true})
|
|
909
|
-
}
|
|
910
|
-
return target[position].input.slice(target[position].start,target[position].end)
|
|
911
|
-
}
|
|
912
|
-
break
|
|
913
|
-
case getIndex:
|
|
914
|
-
return target[getIndex]
|
|
915
|
-
break
|
|
916
|
-
case isChanged:
|
|
917
|
-
return target[isChanged]
|
|
918
|
-
break
|
|
919
|
-
}
|
|
920
|
-
firstParse(target, receiver)
|
|
921
|
-
switch(prop) {
|
|
922
|
-
case source:
|
|
923
|
-
if (meta.access && !meta.access(target, prop, 'get')) {
|
|
924
|
-
return undefined
|
|
925
|
-
}
|
|
926
|
-
return target
|
|
927
|
-
break
|
|
928
|
-
default:
|
|
929
|
-
if (meta.access && !meta.access(target, prop, 'get')) {
|
|
930
|
-
return undefined
|
|
931
|
-
}
|
|
932
|
-
if (Array.isArray(target[prop])) {
|
|
933
|
-
return getArrayProxy(target[prop], target)
|
|
934
|
-
}
|
|
935
|
-
return target[prop]
|
|
936
497
|
break
|
|
937
498
|
}
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
throw new Error('dataspace is immutable')
|
|
942
|
-
}
|
|
943
|
-
switch(prop) {
|
|
944
|
-
case isChanged:
|
|
945
|
-
break
|
|
946
|
-
case source:
|
|
947
|
-
resetObject(target)
|
|
948
|
-
target[position] = value[position]
|
|
949
|
-
target[isParsed] = false
|
|
950
|
-
target[isChanged] = false
|
|
951
|
-
return true
|
|
952
|
-
break
|
|
953
|
-
case resultSet:
|
|
954
|
-
break
|
|
955
|
-
}
|
|
956
|
-
firstParse(target, receiver)
|
|
957
|
-
if (meta.access && !meta.access(target, prop, 'set')) {
|
|
958
|
-
return undefined
|
|
959
|
-
}
|
|
960
|
-
if (value && JSONTag.getType(value)==='object' && !value[isProxy]) {
|
|
961
|
-
value = getNewValueProxy(value)
|
|
962
|
-
}
|
|
963
|
-
if (target[prop] === value) {
|
|
964
|
-
return true
|
|
965
|
-
}
|
|
966
|
-
target[prop] = value
|
|
967
|
-
target[isChanged] = true
|
|
968
|
-
return true
|
|
969
|
-
},
|
|
970
|
-
deleteProperty(target, prop) {
|
|
971
|
-
if (immutable) {
|
|
972
|
-
throw new Error('dataspace is immutable')
|
|
973
|
-
}
|
|
974
|
-
if (meta.access && !meta.access(target, prop, 'deleteProperty')) {
|
|
975
|
-
return undefined
|
|
976
|
-
}
|
|
977
|
-
firstParse(target)
|
|
978
|
-
if (typeof target[prop] === 'undefined') {
|
|
979
|
-
return true
|
|
980
|
-
}
|
|
981
|
-
delete target[prop]
|
|
982
|
-
target[isChanged] = true
|
|
983
|
-
return true
|
|
984
|
-
},
|
|
985
|
-
ownKeys(target) {
|
|
986
|
-
firstParse(target)
|
|
987
|
-
return Reflect.ownKeys(target)
|
|
988
|
-
},
|
|
989
|
-
getOwnPropertyDescriptor(target, prop) {
|
|
990
|
-
firstParse(target)
|
|
991
|
-
return Reflect.getOwnPropertyDescriptor(target, prop)
|
|
992
|
-
},
|
|
993
|
-
defineProperty(target, prop, descriptor) {
|
|
994
|
-
if (immutable) {
|
|
995
|
-
throw new Error('dataspace is immutable')
|
|
996
|
-
}
|
|
997
|
-
if (meta.access && !meta.access(target, prop, 'defineProperty')) {
|
|
998
|
-
return undefined
|
|
999
|
-
}
|
|
1000
|
-
firstParse(target)
|
|
1001
|
-
target[isChanged] = true
|
|
1002
|
-
return Object.defineProperty(target, prop, descriptor)
|
|
1003
|
-
},
|
|
1004
|
-
has(target, prop) {
|
|
1005
|
-
if (meta.access && !meta.access(target, prop, 'has')) {
|
|
1006
|
-
return false
|
|
1007
|
-
}
|
|
1008
|
-
firstParse()
|
|
1009
|
-
return prop in target
|
|
1010
|
-
},
|
|
1011
|
-
setPrototypeOf(target,proto) {
|
|
1012
|
-
throw new Error('changing prototypes is not supported')
|
|
499
|
+
} else {
|
|
500
|
+
value.push(this.ch.charCodeAt(0))
|
|
501
|
+
this.next()
|
|
1013
502
|
}
|
|
1014
503
|
}
|
|
504
|
+
this.error("Syntax error: incomplete string")
|
|
1015
505
|
}
|
|
1016
506
|
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
507
|
+
length()
|
|
508
|
+
{
|
|
509
|
+
this.whitespace()
|
|
510
|
+
this.next('(')
|
|
511
|
+
let numString=''
|
|
512
|
+
while(this.ch>='0' && this.ch<='9') {
|
|
513
|
+
numString += this.ch
|
|
514
|
+
this.next()
|
|
1021
515
|
}
|
|
1022
|
-
if (
|
|
1023
|
-
|
|
1024
|
-
//e.g. odJSONTag and a call to ownKeys triggering the first parse
|
|
1025
|
-
let tag = JSONTag.getType(target)
|
|
1026
|
-
if (tag) {
|
|
1027
|
-
JSONTag.setType(receiver, tag)
|
|
1028
|
-
}
|
|
1029
|
-
let attributes = JSONTag.getAttributes(target)
|
|
1030
|
-
if (attributes) {
|
|
1031
|
-
JSONTag.setAttributes(receiver, attributes)
|
|
1032
|
-
}
|
|
1033
|
-
target[isReceived] = true
|
|
516
|
+
if (this.ch!==')') {
|
|
517
|
+
this.error('Syntax error: not a length')
|
|
1034
518
|
}
|
|
519
|
+
this.next()
|
|
520
|
+
return parseInt(numString)
|
|
1035
521
|
}
|
|
1036
522
|
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
523
|
+
offset()
|
|
524
|
+
{
|
|
525
|
+
this.next('~')
|
|
526
|
+
let numString = ''
|
|
527
|
+
while(this.ch>='0' && this.ch<='9') {
|
|
528
|
+
numString += this.ch
|
|
529
|
+
this.next()
|
|
1040
530
|
}
|
|
531
|
+
if (this.ch=='-') {
|
|
532
|
+
this.next('-')
|
|
533
|
+
let endString = ''
|
|
534
|
+
while(this.ch>='0' && this.ch<='9') {
|
|
535
|
+
endString += this.ch
|
|
536
|
+
this.next()
|
|
537
|
+
}
|
|
538
|
+
return new Slice(parseInt(numString),parseInt(endString)+1) // +1 because array.slice(start,end) slices upto but not including end
|
|
539
|
+
}
|
|
540
|
+
return parseInt(numString)
|
|
1041
541
|
}
|
|
1042
542
|
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
543
|
+
parseValue(position, ob={})
|
|
544
|
+
{
|
|
545
|
+
this.input = position.input
|
|
546
|
+
this.at = position.start
|
|
547
|
+
this.next()
|
|
548
|
+
let result = this.value(ob)
|
|
549
|
+
if (result instanceof JSONTag.Link) {
|
|
550
|
+
result = this.handleLink(result)
|
|
1046
551
|
}
|
|
1047
|
-
let index = meta.resultArray.length
|
|
1048
|
-
meta.resultArray.push('')
|
|
1049
|
-
value[getIndex] = index
|
|
1050
|
-
makeChildProxies(value)
|
|
1051
|
-
let result = new Proxy(value, handlers.newValueHandler)
|
|
1052
|
-
meta.resultArray[index] = result
|
|
1053
552
|
return result
|
|
1054
553
|
}
|
|
1055
554
|
|
|
1056
|
-
|
|
555
|
+
handleLink(link)
|
|
1057
556
|
{
|
|
1058
|
-
let
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
// current offset + length contains jsontag of this value
|
|
1063
|
-
cache[position] = {
|
|
1064
|
-
input,
|
|
1065
|
-
start: at-1,
|
|
1066
|
-
end: at-1+length
|
|
557
|
+
let id = ''+link
|
|
558
|
+
let links = this.meta.unresolved.get(id)
|
|
559
|
+
if (links.length) {
|
|
560
|
+
throw Error('nyi')
|
|
1067
561
|
}
|
|
1068
|
-
at += length
|
|
1069
|
-
next()
|
|
1070
|
-
// newValueHandler makes sure that value[getBuffer] runs stringify
|
|
1071
|
-
// arrayHandler makes sure that changes in the array set targetIsChanged to true
|
|
1072
|
-
return new Proxy(cache, handlers.handler)
|
|
1073
562
|
}
|
|
1074
563
|
|
|
1075
564
|
value = function(ob={})
|
|
1076
565
|
{
|
|
1077
566
|
let tagOb, result, tagName;
|
|
1078
|
-
whitespace()
|
|
1079
|
-
if (ch==='~') {
|
|
1080
|
-
let vOffset = offset()
|
|
567
|
+
this.whitespace()
|
|
568
|
+
if (this.ch==='~') {
|
|
569
|
+
let vOffset = this.offset()
|
|
1081
570
|
if (isSlice(vOffset)) {
|
|
1082
571
|
return vOffset
|
|
1083
572
|
}
|
|
1084
|
-
return meta.resultArray[vOffset]
|
|
573
|
+
return this.meta.resultArray[vOffset]
|
|
1085
574
|
}
|
|
1086
|
-
if (ch==='<') {
|
|
1087
|
-
tagOb = tag()
|
|
575
|
+
if (this.ch==='<') {
|
|
576
|
+
tagOb = this.tag()
|
|
1088
577
|
tagName = tagOb.tagName
|
|
1089
|
-
whitespace()
|
|
578
|
+
this.whitespace()
|
|
1090
579
|
}
|
|
1091
|
-
switch(ch) {
|
|
580
|
+
switch(this.ch) {
|
|
1092
581
|
case '{':
|
|
1093
582
|
if (tagName && tagName!=='object') {
|
|
1094
|
-
|
|
583
|
+
this.typeError(tagName, this.ch)
|
|
1095
584
|
}
|
|
1096
|
-
result = object(ob)
|
|
585
|
+
result = this.object(ob)
|
|
1097
586
|
break
|
|
1098
587
|
case '[':
|
|
1099
588
|
if (tagName && tagName!=='array') {
|
|
1100
|
-
|
|
589
|
+
this.typeError(tagName, this.ch)
|
|
1101
590
|
}
|
|
1102
|
-
result = array()
|
|
591
|
+
result = this.array()
|
|
1103
592
|
break
|
|
1104
593
|
case '"':
|
|
1105
|
-
result = string(tagName)
|
|
594
|
+
result = this.string(tagName)
|
|
1106
595
|
break
|
|
1107
596
|
case '-':
|
|
1108
|
-
result = number(tagName)
|
|
597
|
+
result = this.number(tagName)
|
|
1109
598
|
break
|
|
1110
599
|
default:
|
|
1111
|
-
if (ch>='0' && ch<='9') {
|
|
1112
|
-
result = number(tagName)
|
|
600
|
+
if (this.ch>='0' && this.ch<='9') {
|
|
601
|
+
result = this.number(tagName)
|
|
1113
602
|
} else {
|
|
1114
|
-
result = boolOrNull(tagName)
|
|
603
|
+
result = this.boolOrNull(tagName)
|
|
1115
604
|
}
|
|
1116
605
|
break
|
|
1117
606
|
}
|
|
@@ -1128,7 +617,7 @@ export default function parse(input, meta, immutable=true)
|
|
|
1128
617
|
result = new Number(result)
|
|
1129
618
|
break
|
|
1130
619
|
default:
|
|
1131
|
-
error('Syntax Error: unexpected type '+(typeof result))
|
|
620
|
+
this.error('Syntax Error: unexpected type '+(typeof result))
|
|
1132
621
|
break
|
|
1133
622
|
}
|
|
1134
623
|
}
|
|
@@ -1141,41 +630,139 @@ export default function parse(input, meta, immutable=true)
|
|
|
1141
630
|
}
|
|
1142
631
|
return result
|
|
1143
632
|
}
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
633
|
+
|
|
634
|
+
jump()
|
|
635
|
+
{
|
|
636
|
+
this.next('+')
|
|
637
|
+
return this.number()
|
|
1148
638
|
}
|
|
1149
639
|
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
640
|
+
lengthValue(i)
|
|
641
|
+
{
|
|
642
|
+
this.whitespace()
|
|
643
|
+
if (!this.ch) {
|
|
644
|
+
this.next()
|
|
1154
645
|
}
|
|
1155
646
|
let l, v
|
|
1156
|
-
if (ch=='+') {
|
|
1157
|
-
i += jump()
|
|
647
|
+
if (this.ch=='+') {
|
|
648
|
+
i += this.jump()
|
|
1158
649
|
} else {
|
|
1159
|
-
l = length()
|
|
1160
|
-
v = valueProxy(l,i)
|
|
650
|
+
l = this.length()
|
|
651
|
+
v = this.valueProxy(l,i)
|
|
1161
652
|
}
|
|
1162
653
|
return [l, v, i]
|
|
1163
654
|
}
|
|
1164
655
|
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
656
|
+
valueProxy(length, index)
|
|
657
|
+
{
|
|
658
|
+
let cache = {}
|
|
659
|
+
cache[getIndex] = index
|
|
660
|
+
cache[isChanged] = false
|
|
661
|
+
cache[isParsed] = false
|
|
662
|
+
// current offset + length contains jsontag of this value
|
|
663
|
+
cache[position] = {
|
|
664
|
+
input: this.input,
|
|
665
|
+
start: this.at-1,
|
|
666
|
+
end: this.at-1+length
|
|
667
|
+
}
|
|
668
|
+
this.at += length
|
|
669
|
+
this.next()
|
|
670
|
+
// newValueHandler makes sure that value[getBuffer] runs stringify
|
|
671
|
+
// arrayHandler makes sure that changes in the array set targetIsChanged to true
|
|
672
|
+
let result = new Proxy(cache, this.handlers.defaultHandler)
|
|
673
|
+
this.cachedProxies.set(cache, result)
|
|
674
|
+
return result
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
makeChildProxies(parent)
|
|
678
|
+
{
|
|
679
|
+
Object.entries(parent).forEach(([key,entry]) => {
|
|
680
|
+
if (Array.isArray(entry)) {
|
|
681
|
+
this.makeChildProxies(entry)
|
|
682
|
+
} else if (entry && JSONTag.getType(entry)==='object') {
|
|
683
|
+
if (entry[isProxy]) {
|
|
684
|
+
// do nothing
|
|
685
|
+
} else {
|
|
686
|
+
parent[key] = this.getNewValueProxy(entry)
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
})
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
getArrayProxy(arr, par, handler)
|
|
693
|
+
{
|
|
694
|
+
if (!handler) {
|
|
695
|
+
handler = this.handlers.arrayHandler
|
|
696
|
+
}
|
|
697
|
+
if (!this.cachedProxies.has(arr)) {
|
|
698
|
+
this.cachedProxies.set(arr, new Proxy(arr, handler))
|
|
699
|
+
}
|
|
700
|
+
let aProxy = this.cachedProxies.get(arr)
|
|
701
|
+
aProxy[parent] = par
|
|
702
|
+
return aProxy
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
firstParse(target)
|
|
706
|
+
{
|
|
707
|
+
if (!target[isParsed]) {
|
|
708
|
+
this.parseValue(target[position], target)
|
|
709
|
+
target[isParsed] = true
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
getNewValueProxy(value)
|
|
715
|
+
{
|
|
716
|
+
if (value === null) {
|
|
717
|
+
return null
|
|
718
|
+
}
|
|
719
|
+
let index = this.meta.resultArray.length
|
|
720
|
+
this.meta.resultArray.push('')
|
|
721
|
+
value[getIndex] = index
|
|
722
|
+
this.makeChildProxies(value)
|
|
723
|
+
let result = new Proxy(value, this.handlers.newValueHandler)
|
|
724
|
+
this.cachedProxies.set(value, result)
|
|
725
|
+
this.meta.resultArray[index] = result
|
|
726
|
+
return result
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
parse(input)
|
|
730
|
+
{
|
|
731
|
+
if (typeof input == 'string' || input instanceof String) {
|
|
732
|
+
input = stringToSAB(input)
|
|
733
|
+
}
|
|
734
|
+
if (!(input instanceof Uint8Array)) {
|
|
735
|
+
this.error('parse only accepts Uint8Array or String as input')
|
|
736
|
+
}
|
|
737
|
+
if (!this.meta.resultArray) {
|
|
738
|
+
this.meta.resultArray = []
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
this.ch = ' '
|
|
742
|
+
this.at = 0
|
|
743
|
+
this.input = input
|
|
744
|
+
|
|
745
|
+
let line = 0
|
|
746
|
+
while(this.ch && this.at<this.input.length) {
|
|
747
|
+
let result = this.lengthValue(line) // needs to return current line nr
|
|
748
|
+
this.whitespace()
|
|
749
|
+
line = result[2]
|
|
750
|
+
if (result[1]) {
|
|
751
|
+
if (!this.meta.resultArray[line] || this.meta.resultArray[line][proxyType]=='new') {
|
|
752
|
+
this.meta.resultArray[line] = result[1]
|
|
753
|
+
} else {
|
|
754
|
+
this.meta.resultArray[line][source] = result[1]
|
|
755
|
+
}
|
|
756
|
+
line++
|
|
1176
757
|
}
|
|
1177
|
-
line++
|
|
1178
758
|
}
|
|
759
|
+
return this.meta.resultArray[0]
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
checkUnresolved() {
|
|
763
|
+
// TODO:
|
|
764
|
+
// for now assume there are no <link> objects in od-jsontag
|
|
765
|
+
// JSONTag Parser.checkUnresolved triggers firstParse,
|
|
766
|
+
// while parsing the current object
|
|
1179
767
|
}
|
|
1180
|
-
return meta.resultArray[0]
|
|
1181
768
|
}
|