@muze-nl/od-jsontag 0.3.3 → 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 -993
- package/src/serialize.mjs +8 -9
- package/src/symbols.mjs +1 -0
package/src/parse.mjs
CHANGED
|
@@ -3,11 +3,11 @@ import Null from '@muze-nl/jsontag/src/lib/Null.mjs'
|
|
|
3
3
|
import serialize from './serialize.mjs'
|
|
4
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
|
-
}
|
|
536
|
-
switch(w.toLowerCase()) {
|
|
537
|
-
case 'true':
|
|
538
|
-
if (tagName && tagName!=='boolean') {
|
|
539
|
-
isTypeError(tagName,w)
|
|
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
373
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
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,476 +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()
|
|
650
|
-
}
|
|
651
|
-
error("Input stopped early")
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
let length = function()
|
|
655
|
-
{
|
|
656
|
-
whitespace()
|
|
657
|
-
next('(')
|
|
658
|
-
let numString=''
|
|
659
|
-
while(ch>='0' && ch<='9') {
|
|
660
|
-
numString += ch
|
|
661
|
-
next()
|
|
458
|
+
this.next(',')
|
|
459
|
+
this.whitespace()
|
|
662
460
|
}
|
|
663
|
-
|
|
664
|
-
error('Syntax error: not a length')
|
|
665
|
-
}
|
|
666
|
-
next()
|
|
667
|
-
return parseInt(numString)
|
|
461
|
+
this.error("Input stopped early")
|
|
668
462
|
}
|
|
669
463
|
|
|
670
|
-
|
|
464
|
+
string(tagName)
|
|
671
465
|
{
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
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
497
|
break
|
|
919
498
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
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
|
-
break
|
|
937
|
-
}
|
|
938
|
-
},
|
|
939
|
-
set(target, prop, value, receiver) {
|
|
940
|
-
if (immutable && prop!==resultSet && prop!==source && prop!==isChanged) {
|
|
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
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
JSONTag.setAttributes(receiver, attributes)
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
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()
|
|
515
|
+
}
|
|
516
|
+
if (this.ch!==')') {
|
|
517
|
+
this.error('Syntax error: not a length')
|
|
1031
518
|
}
|
|
519
|
+
this.next()
|
|
520
|
+
return parseInt(numString)
|
|
1032
521
|
}
|
|
1033
522
|
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
523
|
+
offset()
|
|
524
|
+
{
|
|
525
|
+
this.next('~')
|
|
526
|
+
let numString = ''
|
|
527
|
+
while(this.ch>='0' && this.ch<='9') {
|
|
528
|
+
numString += this.ch
|
|
529
|
+
this.next()
|
|
1037
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)
|
|
1038
541
|
}
|
|
1039
542
|
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
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)
|
|
1043
551
|
}
|
|
1044
|
-
let index = meta.resultArray.length
|
|
1045
|
-
meta.resultArray.push('')
|
|
1046
|
-
value[getIndex] = index
|
|
1047
|
-
makeChildProxies(value)
|
|
1048
|
-
let result = new Proxy(value, handlers.newValueHandler)
|
|
1049
|
-
meta.resultArray[index] = result
|
|
1050
552
|
return result
|
|
1051
553
|
}
|
|
1052
554
|
|
|
1053
|
-
|
|
555
|
+
handleLink(link)
|
|
1054
556
|
{
|
|
1055
|
-
let
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
// current offset + length contains jsontag of this value
|
|
1060
|
-
cache[position] = {
|
|
1061
|
-
input,
|
|
1062
|
-
start: at-1,
|
|
1063
|
-
end: at-1+length
|
|
557
|
+
let id = ''+link
|
|
558
|
+
let links = this.meta.unresolved.get(id)
|
|
559
|
+
if (links.length) {
|
|
560
|
+
throw Error('nyi')
|
|
1064
561
|
}
|
|
1065
|
-
at += length
|
|
1066
|
-
next()
|
|
1067
|
-
// newValueHandler makes sure that value[getBuffer] runs stringify
|
|
1068
|
-
// arrayHandler makes sure that changes in the array set targetIsChanged to true
|
|
1069
|
-
return new Proxy(cache, handlers.handler)
|
|
1070
562
|
}
|
|
1071
563
|
|
|
1072
564
|
value = function(ob={})
|
|
1073
565
|
{
|
|
1074
566
|
let tagOb, result, tagName;
|
|
1075
|
-
whitespace()
|
|
1076
|
-
if (ch==='~') {
|
|
1077
|
-
let vOffset = offset()
|
|
567
|
+
this.whitespace()
|
|
568
|
+
if (this.ch==='~') {
|
|
569
|
+
let vOffset = this.offset()
|
|
1078
570
|
if (isSlice(vOffset)) {
|
|
1079
571
|
return vOffset
|
|
1080
572
|
}
|
|
1081
|
-
return meta.resultArray[vOffset]
|
|
573
|
+
return this.meta.resultArray[vOffset]
|
|
1082
574
|
}
|
|
1083
|
-
if (ch==='<') {
|
|
1084
|
-
tagOb = tag()
|
|
575
|
+
if (this.ch==='<') {
|
|
576
|
+
tagOb = this.tag()
|
|
1085
577
|
tagName = tagOb.tagName
|
|
1086
|
-
whitespace()
|
|
578
|
+
this.whitespace()
|
|
1087
579
|
}
|
|
1088
|
-
switch(ch) {
|
|
580
|
+
switch(this.ch) {
|
|
1089
581
|
case '{':
|
|
1090
582
|
if (tagName && tagName!=='object') {
|
|
1091
|
-
|
|
583
|
+
this.typeError(tagName, this.ch)
|
|
1092
584
|
}
|
|
1093
|
-
result = object(ob)
|
|
585
|
+
result = this.object(ob)
|
|
1094
586
|
break
|
|
1095
587
|
case '[':
|
|
1096
588
|
if (tagName && tagName!=='array') {
|
|
1097
|
-
|
|
589
|
+
this.typeError(tagName, this.ch)
|
|
1098
590
|
}
|
|
1099
|
-
result = array()
|
|
591
|
+
result = this.array()
|
|
1100
592
|
break
|
|
1101
593
|
case '"':
|
|
1102
|
-
result = string(tagName)
|
|
594
|
+
result = this.string(tagName)
|
|
1103
595
|
break
|
|
1104
596
|
case '-':
|
|
1105
|
-
result = number(tagName)
|
|
597
|
+
result = this.number(tagName)
|
|
1106
598
|
break
|
|
1107
599
|
default:
|
|
1108
|
-
if (ch>='0' && ch<='9') {
|
|
1109
|
-
result = number(tagName)
|
|
600
|
+
if (this.ch>='0' && this.ch<='9') {
|
|
601
|
+
result = this.number(tagName)
|
|
1110
602
|
} else {
|
|
1111
|
-
result = boolOrNull(tagName)
|
|
603
|
+
result = this.boolOrNull(tagName)
|
|
1112
604
|
}
|
|
1113
605
|
break
|
|
1114
606
|
}
|
|
@@ -1125,7 +617,7 @@ export default function parse(input, meta, immutable=true)
|
|
|
1125
617
|
result = new Number(result)
|
|
1126
618
|
break
|
|
1127
619
|
default:
|
|
1128
|
-
error('Syntax Error: unexpected type '+(typeof result))
|
|
620
|
+
this.error('Syntax Error: unexpected type '+(typeof result))
|
|
1129
621
|
break
|
|
1130
622
|
}
|
|
1131
623
|
}
|
|
@@ -1138,41 +630,139 @@ export default function parse(input, meta, immutable=true)
|
|
|
1138
630
|
}
|
|
1139
631
|
return result
|
|
1140
632
|
}
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
633
|
+
|
|
634
|
+
jump()
|
|
635
|
+
{
|
|
636
|
+
this.next('+')
|
|
637
|
+
return this.number()
|
|
1145
638
|
}
|
|
1146
639
|
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
640
|
+
lengthValue(i)
|
|
641
|
+
{
|
|
642
|
+
this.whitespace()
|
|
643
|
+
if (!this.ch) {
|
|
644
|
+
this.next()
|
|
1151
645
|
}
|
|
1152
646
|
let l, v
|
|
1153
|
-
if (ch=='+') {
|
|
1154
|
-
i += jump()
|
|
647
|
+
if (this.ch=='+') {
|
|
648
|
+
i += this.jump()
|
|
1155
649
|
} else {
|
|
1156
|
-
l = length()
|
|
1157
|
-
v = valueProxy(l,i)
|
|
650
|
+
l = this.length()
|
|
651
|
+
v = this.valueProxy(l,i)
|
|
1158
652
|
}
|
|
1159
653
|
return [l, v, i]
|
|
1160
654
|
}
|
|
1161
655
|
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
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++
|
|
1173
757
|
}
|
|
1174
|
-
line++
|
|
1175
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
|
|
1176
767
|
}
|
|
1177
|
-
return meta.resultArray[0]
|
|
1178
768
|
}
|