dfindexeddb 20240305__py3-none-any.whl → 20240331__py3-none-any.whl
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.
- dfindexeddb/indexeddb/cli.py +112 -0
- dfindexeddb/indexeddb/utils.py +0 -0
- dfindexeddb/leveldb/cli.py +260 -0
- dfindexeddb/leveldb/definitions.py +16 -0
- dfindexeddb/leveldb/descriptor.py +61 -14
- dfindexeddb/leveldb/ldb.py +20 -24
- dfindexeddb/leveldb/log.py +25 -18
- dfindexeddb/leveldb/record.py +102 -0
- dfindexeddb/leveldb/utils.py +116 -0
- dfindexeddb/utils.py +5 -46
- dfindexeddb/version.py +1 -1
- {dfindexeddb-20240305.dist-info → dfindexeddb-20240331.dist-info}/METADATA +74 -30
- dfindexeddb-20240331.dist-info/RECORD +22 -0
- {dfindexeddb-20240305.dist-info → dfindexeddb-20240331.dist-info}/WHEEL +1 -1
- dfindexeddb-20240331.dist-info/entry_points.txt +3 -0
- dfindexeddb/cli.py +0 -180
- dfindexeddb/indexeddb/blink.py +0 -115
- dfindexeddb/indexeddb/chromium.py +0 -1360
- dfindexeddb/indexeddb/definitions.py +0 -306
- dfindexeddb/indexeddb/v8.py +0 -642
- dfindexeddb-20240305.dist-info/RECORD +0 -22
- dfindexeddb-20240305.dist-info/entry_points.txt +0 -2
- {dfindexeddb-20240305.dist-info → dfindexeddb-20240331.dist-info}/AUTHORS +0 -0
- {dfindexeddb-20240305.dist-info → dfindexeddb-20240331.dist-info}/LICENSE +0 -0
- {dfindexeddb-20240305.dist-info → dfindexeddb-20240331.dist-info}/top_level.txt +0 -0
dfindexeddb/indexeddb/v8.py
DELETED
|
@@ -1,642 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
# Copyright 2024 Google LLC
|
|
3
|
-
#
|
|
4
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
# you may not use this file except in compliance with the License.
|
|
6
|
-
# You may obtain a copy of the License at
|
|
7
|
-
#
|
|
8
|
-
# https://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
#
|
|
10
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
# See the License for the specific language governing permissions and
|
|
14
|
-
# limitations under the License.
|
|
15
|
-
"""Parsers for v8 javascript serialized objects."""
|
|
16
|
-
from dataclasses import dataclass
|
|
17
|
-
from datetime import datetime
|
|
18
|
-
import io
|
|
19
|
-
import os
|
|
20
|
-
from typing import Any, BinaryIO, Dict, Optional, Set, Tuple, Union
|
|
21
|
-
|
|
22
|
-
from dfindexeddb import errors
|
|
23
|
-
from dfindexeddb import utils
|
|
24
|
-
from dfindexeddb.indexeddb import definitions
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@dataclass
|
|
28
|
-
class BufferArrayView:
|
|
29
|
-
"""A parsed Javascript BufferArrayView."""
|
|
30
|
-
buffer: bytes
|
|
31
|
-
tag: definitions.V8ArrayBufferViewTag
|
|
32
|
-
offset: int
|
|
33
|
-
length: int
|
|
34
|
-
flags: int
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class JSArray(list):
|
|
38
|
-
"""A parsed Javascript array.
|
|
39
|
-
|
|
40
|
-
This is a wrapper around a standard Python list to allow assigning arbitrary
|
|
41
|
-
properties as is possible in the Javascript equivalent.
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
def __repr__(self):
|
|
45
|
-
array_entries = ", ".join([str(entry) for entry in list(self)])
|
|
46
|
-
properties = ", ".join(
|
|
47
|
-
f'{key}: {value}' for key, value in self.properties.items())
|
|
48
|
-
return f'[{array_entries}, {properties}]'
|
|
49
|
-
|
|
50
|
-
@property
|
|
51
|
-
def properties(self) -> Dict[str, Any]:
|
|
52
|
-
"""Returns the object properties."""
|
|
53
|
-
return self.__dict__
|
|
54
|
-
|
|
55
|
-
def __contains__(self, item):
|
|
56
|
-
return item in self.__dict__
|
|
57
|
-
|
|
58
|
-
def __getitem__(self, name):
|
|
59
|
-
return self.__dict__[name]
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
@dataclass
|
|
63
|
-
class Null:
|
|
64
|
-
"""A parsed Javascript Null."""
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
@dataclass
|
|
68
|
-
class RegExp:
|
|
69
|
-
"""A parsed Javascript RegExp."""
|
|
70
|
-
pattern: str
|
|
71
|
-
flags: int
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
@dataclass(frozen=True)
|
|
75
|
-
class Undefined:
|
|
76
|
-
"""A parsed Javascript undef."""
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
class ValueDeserializer:
|
|
80
|
-
"""A class to deserialize v8 Javascript values/objects.
|
|
81
|
-
|
|
82
|
-
Attributes:
|
|
83
|
-
decoder (utils.StreamDecoder): A StreamDecoder that wraps the binary
|
|
84
|
-
stream containing the serialized Javascript value/object.
|
|
85
|
-
delegate: An instance to delegate deserializing an object
|
|
86
|
-
next_id (int): the next ID to use for a deserialized object.
|
|
87
|
-
objects (dict[int, Any]): a dictionary mapping integer IDs to a
|
|
88
|
-
deserialized object.
|
|
89
|
-
version (int): the version of the serialized Javascript value/object
|
|
90
|
-
"""
|
|
91
|
-
|
|
92
|
-
LATEST_VERSION = 15
|
|
93
|
-
|
|
94
|
-
def __init__(self, stream: BinaryIO, delegate):
|
|
95
|
-
"""Initializes a ValueDeserializer.
|
|
96
|
-
|
|
97
|
-
Args:
|
|
98
|
-
stream: a stream of bytes to be deserialized.
|
|
99
|
-
delegate: an object to delegate additional deserialization of additional
|
|
100
|
-
Javascript types/objects.
|
|
101
|
-
"""
|
|
102
|
-
self.decoder = utils.StreamDecoder(stream)
|
|
103
|
-
self.delegate = delegate
|
|
104
|
-
self.next_id = 0
|
|
105
|
-
self.objects = {}
|
|
106
|
-
self.version = None
|
|
107
|
-
|
|
108
|
-
def GetWireFormatVersion(self) -> int:
|
|
109
|
-
"""Returns the underlying wire format version.
|
|
110
|
-
|
|
111
|
-
Note: Return value is only valid after a call to ReadHeader.
|
|
112
|
-
"""
|
|
113
|
-
return self.version
|
|
114
|
-
|
|
115
|
-
def ReadHeader(self) -> bool:
|
|
116
|
-
"""Reads the header and returns True if the version is supported."""
|
|
117
|
-
if self._ReadTag() != definitions.V8SerializationTag.VERSION:
|
|
118
|
-
return False
|
|
119
|
-
_, self.version = self.decoder.DecodeUint32Varint()
|
|
120
|
-
if self.version > self.LATEST_VERSION:
|
|
121
|
-
return False
|
|
122
|
-
return True
|
|
123
|
-
|
|
124
|
-
def ReadObjectWrapper(self):
|
|
125
|
-
"""Deserializes a V8 object from the current decoder position."""
|
|
126
|
-
original_position = self.decoder.stream.tell()
|
|
127
|
-
result = self._ReadObject()
|
|
128
|
-
if result is None and self.version == 13:
|
|
129
|
-
self.decoder.stream.seek(original_position, os.SEEK_SET)
|
|
130
|
-
result = self._ReadObject()
|
|
131
|
-
raise NotImplementedError('ValueDeserializer.ReadObjectWrapper v13')
|
|
132
|
-
return result
|
|
133
|
-
|
|
134
|
-
def ReadObjectUsingEntireBufferForLegacyFormat(self):
|
|
135
|
-
"""Reads an object, consuming the entire buffer."""
|
|
136
|
-
raise NotImplementedError(
|
|
137
|
-
'ValueDeserializer.ReadObjectUsingEntireBufferForLegacyFormat')
|
|
138
|
-
|
|
139
|
-
def ReadValue(self):
|
|
140
|
-
"""Reads the Javascript value."""
|
|
141
|
-
if self.GetWireFormatVersion() > 0:
|
|
142
|
-
return self.ReadObjectWrapper()
|
|
143
|
-
return self.ReadObjectUsingEntireBufferForLegacyFormat()
|
|
144
|
-
|
|
145
|
-
def _PeekTag(self) -> Optional[definitions.V8SerializationTag]:
|
|
146
|
-
"""Peeks the next serialization tag from the current decoder position.
|
|
147
|
-
|
|
148
|
-
Returns:
|
|
149
|
-
The serialization tag or None if there is no more bytes to read.
|
|
150
|
-
"""
|
|
151
|
-
try:
|
|
152
|
-
_, tag_value = self.decoder.PeekBytes(1)
|
|
153
|
-
except errors.DecoderError:
|
|
154
|
-
return None
|
|
155
|
-
return definitions.V8SerializationTag(tag_value[0])
|
|
156
|
-
|
|
157
|
-
def _ReadTag(self) -> definitions.V8SerializationTag:
|
|
158
|
-
"""Returns the next non-padding serialization tag.
|
|
159
|
-
|
|
160
|
-
Raises:
|
|
161
|
-
errors.ParserError: when an invalid v8 tag is read.
|
|
162
|
-
"""
|
|
163
|
-
while True:
|
|
164
|
-
_, tag_value = self.decoder.ReadBytes(1)
|
|
165
|
-
try:
|
|
166
|
-
tag = definitions.V8SerializationTag(tag_value[0])
|
|
167
|
-
except ValueError as error:
|
|
168
|
-
raise errors.ParserError(f'Invalid v8 tag value {tag_value}') from error
|
|
169
|
-
if tag != definitions.V8SerializationTag.PADDING:
|
|
170
|
-
return tag
|
|
171
|
-
|
|
172
|
-
def _ConsumeTag(self, peeked_tag: definitions.V8SerializationTag):
|
|
173
|
-
"""Consumes the next serialization tag.
|
|
174
|
-
|
|
175
|
-
Args:
|
|
176
|
-
peeked_tag: the tag that is expected to be read from the current position.
|
|
177
|
-
|
|
178
|
-
Raises:
|
|
179
|
-
errors.ParserError: if the peeked tag is not read.
|
|
180
|
-
"""
|
|
181
|
-
tag = self._ReadTag()
|
|
182
|
-
if tag != peeked_tag:
|
|
183
|
-
raise errors.ParserError(f'Unexpected tag {tag} found.')
|
|
184
|
-
|
|
185
|
-
def _ReadObject(self):
|
|
186
|
-
"""Reads a Javascript object from the current position."""
|
|
187
|
-
_, result = self._ReadObjectInternal()
|
|
188
|
-
tag = self._PeekTag()
|
|
189
|
-
if tag and tag == definitions.V8SerializationTag.ARRAY_BUFFER_VIEW:
|
|
190
|
-
self._ConsumeTag(tag)
|
|
191
|
-
result = self._ReadJSArrayBufferView(result)
|
|
192
|
-
return result
|
|
193
|
-
|
|
194
|
-
def _ReadObjectInternal(self) -> Tuple[definitions.V8SerializationTag, Any]:
|
|
195
|
-
"""Reads a Javascript object from the current position.
|
|
196
|
-
|
|
197
|
-
Returns:
|
|
198
|
-
a tuple of the serialization tag and the parsed object.
|
|
199
|
-
"""
|
|
200
|
-
tag = self._ReadTag()
|
|
201
|
-
if tag == definitions.V8SerializationTag.VERIFY_OBJECT_COUNT:
|
|
202
|
-
_ = self.decoder.DecodeUint32Varint()
|
|
203
|
-
parsed_object = self._ReadObject()
|
|
204
|
-
elif tag == definitions.V8SerializationTag.UNDEFINED:
|
|
205
|
-
parsed_object = Undefined()
|
|
206
|
-
elif tag == definitions.V8SerializationTag.NULL:
|
|
207
|
-
parsed_object = Null()
|
|
208
|
-
elif tag == definitions.V8SerializationTag.TRUE:
|
|
209
|
-
parsed_object = True
|
|
210
|
-
elif tag == definitions.V8SerializationTag.FALSE:
|
|
211
|
-
parsed_object = False
|
|
212
|
-
elif tag == definitions.V8SerializationTag.INT32:
|
|
213
|
-
_, parsed_object = self.decoder.DecodeInt32Varint()
|
|
214
|
-
elif tag == definitions.V8SerializationTag.UINT32:
|
|
215
|
-
_, parsed_object = self.decoder.DecodeUint32Varint()
|
|
216
|
-
elif tag == definitions.V8SerializationTag.DOUBLE:
|
|
217
|
-
_, parsed_object = self.decoder.DecodeDouble()
|
|
218
|
-
elif tag == definitions.V8SerializationTag.BIGINT:
|
|
219
|
-
parsed_object = self.ReadBigInt()
|
|
220
|
-
elif tag == definitions.V8SerializationTag.UTF8_STRING:
|
|
221
|
-
parsed_object = self.ReadUTF8String()
|
|
222
|
-
elif tag == definitions.V8SerializationTag.ONE_BYTE_STRING:
|
|
223
|
-
parsed_object = self.ReadOneByteString()
|
|
224
|
-
elif tag == definitions.V8SerializationTag.TWO_BYTE_STRING:
|
|
225
|
-
parsed_object = self.ReadTwoByteString()
|
|
226
|
-
elif tag == definitions.V8SerializationTag.OBJECT_REFERENCE:
|
|
227
|
-
_, object_id = self.decoder.DecodeUint32Varint()
|
|
228
|
-
parsed_object = self.objects[object_id]
|
|
229
|
-
elif tag == definitions.V8SerializationTag.BEGIN_JS_OBJECT:
|
|
230
|
-
parsed_object = self._ReadJSObject()
|
|
231
|
-
elif tag == definitions.V8SerializationTag.BEGIN_SPARSE_JS_ARRAY:
|
|
232
|
-
parsed_object = self.ReadSparseJSArray()
|
|
233
|
-
elif tag == definitions.V8SerializationTag.BEGIN_DENSE_JS_ARRAY:
|
|
234
|
-
parsed_object = self.ReadDenseJSArray()
|
|
235
|
-
elif tag == definitions.V8SerializationTag.DATE:
|
|
236
|
-
parsed_object = self._ReadJSDate()
|
|
237
|
-
elif tag in (
|
|
238
|
-
definitions.V8SerializationTag.TRUE_OBJECT,
|
|
239
|
-
definitions.V8SerializationTag.FALSE_OBJECT,
|
|
240
|
-
definitions.V8SerializationTag.NUMBER_OBJECT,
|
|
241
|
-
definitions.V8SerializationTag.BIGINT_OBJECT,
|
|
242
|
-
definitions.V8SerializationTag.STRING_OBJECT):
|
|
243
|
-
parsed_object = self._ReadJSPrimitiveWrapper(tag)
|
|
244
|
-
elif tag == definitions.V8SerializationTag.REGEXP:
|
|
245
|
-
parsed_object = self._ReadJSRegExp()
|
|
246
|
-
elif tag == definitions.V8SerializationTag.BEGIN_JS_MAP:
|
|
247
|
-
parsed_object = self._ReadJSMap()
|
|
248
|
-
elif tag == definitions.V8SerializationTag.BEGIN_JS_SET:
|
|
249
|
-
parsed_object = self._ReadJSSet()
|
|
250
|
-
elif tag == definitions.V8SerializationTag.ARRAY_BUFFER:
|
|
251
|
-
parsed_object = self._ReadJSArrayBuffer(
|
|
252
|
-
is_shared=False, is_resizable=False)
|
|
253
|
-
elif tag == definitions.V8SerializationTag.RESIZABLE_ARRAY_BUFFER:
|
|
254
|
-
parsed_object = self._ReadJSArrayBuffer(
|
|
255
|
-
is_shared=False, is_resizable=True)
|
|
256
|
-
elif tag == definitions.V8SerializationTag.SHARED_ARRAY_BUFFER:
|
|
257
|
-
parsed_object = self._ReadJSArrayBuffer(
|
|
258
|
-
is_shared=True, is_resizable=False)
|
|
259
|
-
elif tag == definitions.V8SerializationTag.ERROR:
|
|
260
|
-
parsed_object = self._ReadJSError()
|
|
261
|
-
elif tag == definitions.V8SerializationTag.WASM_MODULE_TRANSFER:
|
|
262
|
-
parsed_object = self._ReadWasmModuleTransfer()
|
|
263
|
-
elif tag == definitions.V8SerializationTag.WASM_MEMORY_TRANSFER:
|
|
264
|
-
parsed_object = self._ReadWasmMemory()
|
|
265
|
-
elif tag == definitions.V8SerializationTag.HOST_OBJECT:
|
|
266
|
-
parsed_object = self.ReadHostObject()
|
|
267
|
-
elif (
|
|
268
|
-
tag == definitions.V8SerializationTag.SHARED_OBJECT and
|
|
269
|
-
self.version >= 15):
|
|
270
|
-
parsed_object = self.ReadSharedObject()
|
|
271
|
-
elif self.version < 13:
|
|
272
|
-
self.decoder.stream.seek(-1)
|
|
273
|
-
parsed_object = self.ReadHostObject()
|
|
274
|
-
else:
|
|
275
|
-
parsed_object = None
|
|
276
|
-
return tag, parsed_object
|
|
277
|
-
|
|
278
|
-
def ReadString(self) -> str:
|
|
279
|
-
"""Reads a string from the current position.
|
|
280
|
-
|
|
281
|
-
Raises:
|
|
282
|
-
errors.ParserError: if the parsed object is not a string.
|
|
283
|
-
"""
|
|
284
|
-
if self.version < 12:
|
|
285
|
-
return self.ReadUTF8String()
|
|
286
|
-
|
|
287
|
-
str_obj = self._ReadObject()
|
|
288
|
-
if not isinstance(str_obj, str):
|
|
289
|
-
raise errors.ParserError('Not a string')
|
|
290
|
-
return str_obj
|
|
291
|
-
|
|
292
|
-
def ReadBigInt(self) -> int:
|
|
293
|
-
"""Reads a Javascript Bigint from the current position."""
|
|
294
|
-
bit_field = self.decoder.DecodeUint32Varint()[1]
|
|
295
|
-
byte_count = bit_field >> 1
|
|
296
|
-
signed = bool(bit_field & 0x1)
|
|
297
|
-
_, bigint = self.decoder.DecodeInt(byte_count=byte_count)
|
|
298
|
-
return -bigint if signed else bigint
|
|
299
|
-
|
|
300
|
-
def ReadUTF8String(self) -> str:
|
|
301
|
-
"""Reads a UTF-8 string from the current position."""
|
|
302
|
-
count = self.decoder.DecodeUint32Varint()[1]
|
|
303
|
-
buffer = self.decoder.ReadBytes(count=count)[1]
|
|
304
|
-
return buffer.decode('utf-8')
|
|
305
|
-
|
|
306
|
-
def ReadOneByteString(self) -> str:
|
|
307
|
-
"""Reads a one-byte string from the current position.
|
|
308
|
-
|
|
309
|
-
The raw bytes are decoded using latin-1 encoding.
|
|
310
|
-
"""
|
|
311
|
-
length = self.decoder.DecodeUint32Varint()[1]
|
|
312
|
-
buffer = self.decoder.ReadBytes(count=length)[1]
|
|
313
|
-
return buffer.decode('latin-1')
|
|
314
|
-
|
|
315
|
-
def ReadTwoByteString(self) -> str:
|
|
316
|
-
"""Reads a UTF-16-LE string from the current position."""
|
|
317
|
-
length = self.decoder.DecodeUint32Varint()[1]
|
|
318
|
-
buffer = self.decoder.ReadBytes(count=length)[1]
|
|
319
|
-
return buffer.decode('utf-16-le')
|
|
320
|
-
|
|
321
|
-
def ReadExpectedString(self) -> Optional[str]:
|
|
322
|
-
"""Reads a string from the current position, None if there is no tag or
|
|
323
|
-
invalid byte length.
|
|
324
|
-
|
|
325
|
-
A string can be UTF-8/one-byte/two-byte.
|
|
326
|
-
|
|
327
|
-
Raises:
|
|
328
|
-
errors.ParserError: if there is an unexpected serialization tag."""
|
|
329
|
-
tag = self._ReadTag()
|
|
330
|
-
if not tag:
|
|
331
|
-
return None
|
|
332
|
-
_, byte_length = self.decoder.DecodeUint32Varint()
|
|
333
|
-
if not byte_length:
|
|
334
|
-
return None
|
|
335
|
-
|
|
336
|
-
_, raw_bytes = self.decoder.ReadBytes(count=byte_length)
|
|
337
|
-
|
|
338
|
-
if tag == definitions.V8SerializationTag.ONE_BYTE_STRING:
|
|
339
|
-
return raw_bytes.decode('latin-1')
|
|
340
|
-
if tag == definitions.V8SerializationTag.TWO_BYTE_STRING:
|
|
341
|
-
return raw_bytes.decode('utf-16-le')
|
|
342
|
-
if tag == definitions.V8SerializationTag.UTF8_STRING:
|
|
343
|
-
return raw_bytes.decode('utf-8')
|
|
344
|
-
raise errors.ParserError(f'Unexpected serialization tag {tag}.')
|
|
345
|
-
|
|
346
|
-
def _ReadJSObject(self) -> Dict:
|
|
347
|
-
"""Reads a JSObject from the current position.
|
|
348
|
-
|
|
349
|
-
Raises:
|
|
350
|
-
errors.ParserError: if an unexpected number of properties have been
|
|
351
|
-
read.
|
|
352
|
-
"""
|
|
353
|
-
next_id = self._GetNextId()
|
|
354
|
-
js_object = {}
|
|
355
|
-
|
|
356
|
-
num_properties = self._ReadJSObjectProperties(
|
|
357
|
-
js_object, definitions.V8SerializationTag.END_JS_OBJECT)
|
|
358
|
-
_, expected_number_properties = self.decoder.DecodeUint32Varint()
|
|
359
|
-
if expected_number_properties != num_properties:
|
|
360
|
-
raise errors.ParserError('Unexpected number of properties')
|
|
361
|
-
|
|
362
|
-
self.objects[next_id] = js_object
|
|
363
|
-
return js_object
|
|
364
|
-
|
|
365
|
-
def _ReadJSObjectProperties(
|
|
366
|
-
self,
|
|
367
|
-
js_object: Union[Dict, JSArray],
|
|
368
|
-
end_tag: definitions.V8SerializationTag
|
|
369
|
-
) -> int:
|
|
370
|
-
"""Reads key-value properties and sets them to the given js_object.
|
|
371
|
-
|
|
372
|
-
Args:
|
|
373
|
-
js_object: the Javascript object to set the parsed properties to.
|
|
374
|
-
end_tag: the end tag that signifies there are no more properties to read.
|
|
375
|
-
|
|
376
|
-
Returns:
|
|
377
|
-
the number of properties that were read.
|
|
378
|
-
"""
|
|
379
|
-
num_properties = 0
|
|
380
|
-
while self._PeekTag() != end_tag:
|
|
381
|
-
key = self._ReadObject()
|
|
382
|
-
value = self._ReadObject()
|
|
383
|
-
js_object[key] = value
|
|
384
|
-
num_properties += 1
|
|
385
|
-
self._ConsumeTag(end_tag)
|
|
386
|
-
return num_properties
|
|
387
|
-
|
|
388
|
-
def _GetNextId(self) -> int:
|
|
389
|
-
"""Gets the next object ID."""
|
|
390
|
-
next_id = self.next_id
|
|
391
|
-
self.next_id += 1
|
|
392
|
-
return next_id
|
|
393
|
-
|
|
394
|
-
def ReadSparseJSArray(self) -> JSArray:
|
|
395
|
-
"""Reads a sparse encoded JSArray from the current position.
|
|
396
|
-
|
|
397
|
-
Raises:
|
|
398
|
-
errors.ParserError: if there is an unexpected property or array length.
|
|
399
|
-
"""
|
|
400
|
-
next_id = self._GetNextId()
|
|
401
|
-
|
|
402
|
-
js_array = JSArray()
|
|
403
|
-
_, length = self.decoder.DecodeUint32Varint()
|
|
404
|
-
for _ in range(length):
|
|
405
|
-
js_array.append(Undefined())
|
|
406
|
-
|
|
407
|
-
num_properties = self._ReadJSObjectProperties(
|
|
408
|
-
js_array.__dict__, definitions.V8SerializationTag.END_SPARSE_JS_ARRAY)
|
|
409
|
-
_, expected_num_properties = self.decoder.DecodeUint32Varint()
|
|
410
|
-
_, expected_length = self.decoder.DecodeUint32Varint()
|
|
411
|
-
|
|
412
|
-
if num_properties != expected_num_properties:
|
|
413
|
-
raise errors.ParserError('Unexpected property length')
|
|
414
|
-
if length != expected_length:
|
|
415
|
-
raise errors.ParserError('Unexpected array length')
|
|
416
|
-
self.objects[next_id] = js_array
|
|
417
|
-
return js_array
|
|
418
|
-
|
|
419
|
-
def ReadDenseJSArray(self) -> JSArray:
|
|
420
|
-
"""Reads a dense encoded JSArray from the current position.
|
|
421
|
-
|
|
422
|
-
Raises:
|
|
423
|
-
errors.ParserError: if there is an unexpected property or array length.
|
|
424
|
-
"""
|
|
425
|
-
next_id = self._GetNextId()
|
|
426
|
-
|
|
427
|
-
js_array = JSArray()
|
|
428
|
-
_, length = self.decoder.DecodeUint32Varint()
|
|
429
|
-
for _ in range(length):
|
|
430
|
-
tag = self._PeekTag()
|
|
431
|
-
if tag == definitions.V8SerializationTag.THE_HOLE:
|
|
432
|
-
self._ConsumeTag(tag)
|
|
433
|
-
continue
|
|
434
|
-
array_object = self._ReadObject()
|
|
435
|
-
|
|
436
|
-
if self.version < 11 and isinstance(array_object, Undefined):
|
|
437
|
-
continue
|
|
438
|
-
js_array.append(array_object)
|
|
439
|
-
|
|
440
|
-
num_properties = self._ReadJSObjectProperties(
|
|
441
|
-
js_array.__dict__, definitions.V8SerializationTag.END_DENSE_JS_ARRAY)
|
|
442
|
-
_, expected_num_properties = self.decoder.DecodeUint32Varint()
|
|
443
|
-
_, expected_length = self.decoder.DecodeUint32Varint()
|
|
444
|
-
if num_properties != expected_num_properties:
|
|
445
|
-
raise errors.ParserError('Unexpected property length')
|
|
446
|
-
if length != expected_length:
|
|
447
|
-
raise errors.ParserError('Unexpected array length')
|
|
448
|
-
self.objects[next_id] = js_array
|
|
449
|
-
return js_array
|
|
450
|
-
|
|
451
|
-
def _ReadJSDate(self) -> datetime:
|
|
452
|
-
"""Reads a JSDate from the current position."""
|
|
453
|
-
next_id = self._GetNextId()
|
|
454
|
-
|
|
455
|
-
_, value = self.decoder.DecodeDouble()
|
|
456
|
-
result = datetime.utcfromtimestamp(value/1000.0)
|
|
457
|
-
self.objects[next_id] = result
|
|
458
|
-
return result
|
|
459
|
-
|
|
460
|
-
def _ReadJSPrimitiveWrapper(
|
|
461
|
-
self,
|
|
462
|
-
tag: definitions.V8SerializationTag
|
|
463
|
-
) -> Union[bool, float, int, str]:
|
|
464
|
-
"""Reads a Javascript wrapped primitive.
|
|
465
|
-
|
|
466
|
-
Args:
|
|
467
|
-
tag: the serialization tag.
|
|
468
|
-
|
|
469
|
-
Returns:
|
|
470
|
-
the parsed value.
|
|
471
|
-
|
|
472
|
-
Raises:
|
|
473
|
-
errors.ParserError: if the given tag is not a Javascript wrapped
|
|
474
|
-
primitive.
|
|
475
|
-
"""
|
|
476
|
-
next_id = self._GetNextId()
|
|
477
|
-
|
|
478
|
-
if tag == definitions.V8SerializationTag.TRUE_OBJECT:
|
|
479
|
-
value = True
|
|
480
|
-
elif tag == definitions.V8SerializationTag.FALSE_OBJECT:
|
|
481
|
-
value = False
|
|
482
|
-
elif tag == definitions.V8SerializationTag.NUMBER_OBJECT:
|
|
483
|
-
_, value = self.decoder.DecodeDouble()
|
|
484
|
-
elif tag == definitions.V8SerializationTag.BIGINT_OBJECT:
|
|
485
|
-
value = self.ReadBigInt()
|
|
486
|
-
elif tag == definitions.V8SerializationTag.STRING_OBJECT:
|
|
487
|
-
value = self.ReadString()
|
|
488
|
-
else:
|
|
489
|
-
raise errors.ParserError(f'Invalid tag {tag}')
|
|
490
|
-
|
|
491
|
-
self.objects[next_id] = value
|
|
492
|
-
return value
|
|
493
|
-
|
|
494
|
-
def _ReadJSRegExp(self) -> RegExp:
|
|
495
|
-
"""Reads a Javscript regular expression from the current position."""
|
|
496
|
-
next_id = self._GetNextId()
|
|
497
|
-
pattern = self.ReadString()
|
|
498
|
-
_, flags = self.decoder.DecodeUint32Varint() # TODO: verify flags
|
|
499
|
-
regexp = RegExp(pattern=pattern, flags=flags)
|
|
500
|
-
self.objects[next_id] = regexp
|
|
501
|
-
return regexp
|
|
502
|
-
|
|
503
|
-
def _ReadJSMap(self) -> Dict[Any, Any]:
|
|
504
|
-
"""Reads a Javascript map (dictionary) from the current position.
|
|
505
|
-
|
|
506
|
-
Raises:
|
|
507
|
-
errors.ParserError: on an unexpected map length.
|
|
508
|
-
"""
|
|
509
|
-
next_id = self._GetNextId()
|
|
510
|
-
js_map = {}
|
|
511
|
-
|
|
512
|
-
tag = self._PeekTag()
|
|
513
|
-
while tag != definitions.V8SerializationTag.END_JS_MAP:
|
|
514
|
-
key = self._ReadObject()
|
|
515
|
-
value = self._ReadObject()
|
|
516
|
-
js_map[key] = value
|
|
517
|
-
tag = self._PeekTag()
|
|
518
|
-
self._ConsumeTag(definitions.V8SerializationTag.END_JS_MAP)
|
|
519
|
-
|
|
520
|
-
_, expected_length = self.decoder.DecodeUint32Varint()
|
|
521
|
-
if len(js_map) * 2 != expected_length:
|
|
522
|
-
raise errors.ParserError('unexpected length')
|
|
523
|
-
|
|
524
|
-
self.objects[next_id] = js_map
|
|
525
|
-
return js_map
|
|
526
|
-
|
|
527
|
-
def _ReadJSSet(self) -> Set[Any]:
|
|
528
|
-
"""Reads a Javascript set from the current position.
|
|
529
|
-
|
|
530
|
-
Raises:
|
|
531
|
-
errors.ParserError: on an unexpected map length.
|
|
532
|
-
"""
|
|
533
|
-
next_id = self._GetNextId()
|
|
534
|
-
|
|
535
|
-
js_set = set()
|
|
536
|
-
tag = self._PeekTag()
|
|
537
|
-
while tag != definitions.V8SerializationTag.END_JS_SET:
|
|
538
|
-
element = self._ReadObject()
|
|
539
|
-
js_set.add(element)
|
|
540
|
-
tag = self._PeekTag()
|
|
541
|
-
self._ConsumeTag(definitions.V8SerializationTag.END_JS_SET)
|
|
542
|
-
|
|
543
|
-
_, expected_length = self.decoder.DecodeUint32Varint()
|
|
544
|
-
if len(js_set) != expected_length:
|
|
545
|
-
raise ValueError('unexpected length')
|
|
546
|
-
|
|
547
|
-
self.objects[next_id] = js_set
|
|
548
|
-
return js_set
|
|
549
|
-
|
|
550
|
-
def _ReadJSArrayBuffer(
|
|
551
|
-
self, is_shared: bool, is_resizable: bool) -> bytes:
|
|
552
|
-
"""Reads a Javascript ArrayBuffer from the current position.
|
|
553
|
-
|
|
554
|
-
Args:
|
|
555
|
-
is_shared: True if the buffer is shared, False otherwise.
|
|
556
|
-
is_resizable: True if the buffer is resizable, False otherwise.
|
|
557
|
-
"""
|
|
558
|
-
next_id = self._GetNextId()
|
|
559
|
-
array_buffer = b''
|
|
560
|
-
|
|
561
|
-
if is_shared:
|
|
562
|
-
raise NotImplementedError('Shared ArrayBuffer not supported yet')
|
|
563
|
-
|
|
564
|
-
_, byte_length = self.decoder.DecodeUint32Varint()
|
|
565
|
-
max_byte_length = byte_length
|
|
566
|
-
if is_resizable:
|
|
567
|
-
_, max_byte_length = self.decoder.DecodeUint32Varint()
|
|
568
|
-
if byte_length > max_byte_length:
|
|
569
|
-
return array_buffer
|
|
570
|
-
if byte_length:
|
|
571
|
-
_, array_buffer = self.decoder.ReadBytes(byte_length)
|
|
572
|
-
|
|
573
|
-
self.objects[next_id] = array_buffer
|
|
574
|
-
return array_buffer
|
|
575
|
-
|
|
576
|
-
def _ReadJSArrayBufferView(self, buffer):
|
|
577
|
-
"""Reads a JSArrayBufferView from the current position."""
|
|
578
|
-
_, tag = self.decoder.ReadBytes(1)
|
|
579
|
-
_, byte_offset = self.decoder.DecodeUint32Varint()
|
|
580
|
-
_, byte_length = self.decoder.DecodeUint32Varint()
|
|
581
|
-
|
|
582
|
-
if self.version >= 14: # or version_13_broken_data_mode
|
|
583
|
-
_, flags = self.decoder.DecodeUint32Varint()
|
|
584
|
-
else:
|
|
585
|
-
flags = 0
|
|
586
|
-
|
|
587
|
-
return BufferArrayView(
|
|
588
|
-
buffer=buffer,
|
|
589
|
-
tag=definitions.V8ArrayBufferViewTag(tag[0]),
|
|
590
|
-
offset=byte_offset,
|
|
591
|
-
length=byte_length,
|
|
592
|
-
flags=flags)
|
|
593
|
-
|
|
594
|
-
def _ReadJSError(self):
|
|
595
|
-
"""Reads a Javascript error from the current position."""
|
|
596
|
-
raise NotImplementedError('ValueDeserializer.ReadJSError')
|
|
597
|
-
|
|
598
|
-
def _ReadWasmModuleTransfer(self):
|
|
599
|
-
"""Reads a Wasm module transfer object from the current position."""
|
|
600
|
-
raise NotImplementedError('ValueDeserializer.ReadWasmModuleTransfer')
|
|
601
|
-
|
|
602
|
-
def _ReadWasmMemory(self):
|
|
603
|
-
"""Reads a Wasm memory object from the current position."""
|
|
604
|
-
raise NotImplementedError('ValueDeserializer.ReadWasmMemory')
|
|
605
|
-
|
|
606
|
-
def ReadSharedObject(self) -> Any:
|
|
607
|
-
"""Reads a shared object from the current position."""
|
|
608
|
-
#_, shared_object_id = self.decoder.DecodeUint32Varint()
|
|
609
|
-
raise NotImplementedError('ValueDeserializer.ReadSharedObject')
|
|
610
|
-
|
|
611
|
-
def ReadHostObject(self):
|
|
612
|
-
"""Reads a Host object using the delegate object.
|
|
613
|
-
|
|
614
|
-
Raises:
|
|
615
|
-
errors.ParserError: when the delegate object is None.
|
|
616
|
-
"""
|
|
617
|
-
next_id = self._GetNextId()
|
|
618
|
-
if not self.delegate:
|
|
619
|
-
raise errors.ParserError('No delegate to read host object.')
|
|
620
|
-
host_object = self.delegate.ReadHostObject()
|
|
621
|
-
self.objects[next_id] = host_object
|
|
622
|
-
return host_object
|
|
623
|
-
|
|
624
|
-
@classmethod
|
|
625
|
-
def FromBytes(cls, data: bytes, delegate: Any) -> Any:
|
|
626
|
-
"""Returns a deserialized javascript object from the data.
|
|
627
|
-
|
|
628
|
-
Args:
|
|
629
|
-
data: the data to deserialize/parse.
|
|
630
|
-
delegate: an object to delegate parsing additional Javascript objects.
|
|
631
|
-
|
|
632
|
-
Returns:
|
|
633
|
-
A python representation of the parsed javascript object.
|
|
634
|
-
|
|
635
|
-
Raises:
|
|
636
|
-
errors.ParserError: if there is an invalid V8 javascript header.
|
|
637
|
-
"""
|
|
638
|
-
stream = io.BytesIO(data)
|
|
639
|
-
deserializer = cls(stream, delegate)
|
|
640
|
-
if not deserializer.ReadHeader():
|
|
641
|
-
raise errors.ParserError('Invalid V8 header')
|
|
642
|
-
return deserializer.ReadObjectWrapper()
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
dfindexeddb/__init__.py,sha256=KPYL9__l8od6_OyDfGRTgaJ6iy_fqIgZ-dS2S-e3Rac,599
|
|
2
|
-
dfindexeddb/cli.py,sha256=fm7iGA5k1VVIc4jT80w8yQ2kb6h9AucByikwNFNuG3A,5593
|
|
3
|
-
dfindexeddb/errors.py,sha256=PNpwyf_lrPc4TE77oAakX3mu5D_YcP3f80wq8Y1LkvY,749
|
|
4
|
-
dfindexeddb/utils.py,sha256=fp4NaJhJR1LI4THH3PPo_dGyuMkQ6sOtk-l3e9lIdLY,10349
|
|
5
|
-
dfindexeddb/version.py,sha256=KH2nfTUTTcPB19XDYtCGJUOAturiQSDckkQvGgYWdYg,750
|
|
6
|
-
dfindexeddb/indexeddb/__init__.py,sha256=kExXSVBCTKCD5BZJkdMfUMqGksH-DMJxP2_lI0gq-BE,575
|
|
7
|
-
dfindexeddb/indexeddb/blink.py,sha256=MblpYfv-ByG7n_fjYKu2EUhpfVJdUveoW4oSAg5T4tY,3534
|
|
8
|
-
dfindexeddb/indexeddb/chromium.py,sha256=6aePZ7quQzQgHi2KYtlmrjeWZyURGdUFYKIPH80cEAs,44696
|
|
9
|
-
dfindexeddb/indexeddb/definitions.py,sha256=yline3y3gmZx6s-dwjpPDNs5HO4zT6KZqPWQfEsHDoM,7413
|
|
10
|
-
dfindexeddb/indexeddb/v8.py,sha256=ldqpc9T1kG7BOdjnHjQ5hNO9OCXZ3_Zd6vRSpC-NrEA,21893
|
|
11
|
-
dfindexeddb/leveldb/__init__.py,sha256=KPYL9__l8od6_OyDfGRTgaJ6iy_fqIgZ-dS2S-e3Rac,599
|
|
12
|
-
dfindexeddb/leveldb/definitions.py,sha256=d34YBXNRJZklS-KLKOKiwf_ojxevQedYaoJoNGaeM5g,1109
|
|
13
|
-
dfindexeddb/leveldb/descriptor.py,sha256=tfJ0Smk4apUuVZIxEWDTPPjNaTqVtRndA1YsZdHlceI,10394
|
|
14
|
-
dfindexeddb/leveldb/ldb.py,sha256=dOZpzh9WHL3qwfTyIJFn6-OaApTNnqTHeJgXYwOM1-c,7931
|
|
15
|
-
dfindexeddb/leveldb/log.py,sha256=5m6OADTM7BP3AWbamlqAwTn_UGcG2UXZz1YpCq1o4Gk,8858
|
|
16
|
-
dfindexeddb-20240305.dist-info/AUTHORS,sha256=QbvjbAom57fpEkekkCVFUj0B9KUMGraR510aUMBC-PE,286
|
|
17
|
-
dfindexeddb-20240305.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
18
|
-
dfindexeddb-20240305.dist-info/METADATA,sha256=_iqPyDYZsvVd-ITp--C8yyfwB11gs_D1JIIKFDAezW4,15933
|
|
19
|
-
dfindexeddb-20240305.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
20
|
-
dfindexeddb-20240305.dist-info/entry_points.txt,sha256=UsfPLLhTiVAAtZ8Rq3ZR7JNFGMuHqJy-tugGWonQWtc,52
|
|
21
|
-
dfindexeddb-20240305.dist-info/top_level.txt,sha256=X9OTaub1c8S_JJ7g-f8JdkhhdiZ4x1j4eni1hdUCwE4,12
|
|
22
|
-
dfindexeddb-20240305.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|