Skip to content

Commit b1d51aa

Browse files
authored
Merge pull request #5 from Y0ursTruly/new-datatypes
New datatype (Date) support added
2 parents d40602d + aecc1bf commit b1d51aa

6 files changed

Lines changed: 96 additions & 33 deletions

File tree

README.md

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Share (and sync) Objects Online with the power of websockets. Keys, Values AND R
33
<br>
44
**Please note**:
55
- To view example usage of the modules this library provides, please refer to the _[tests](https://github.com/Y0ursTruly/webject/blob/main/tests.js)_
6-
- Supporting the `Date` type soon. In the meantime it is advised to `Date` instances into their string or number equivalent
6+
- Better example usages would be included later on other than the test file
77

88
# Installation
99
Multiple ways
@@ -332,6 +332,42 @@ undefined
332332
</ul>
333333

334334
# Structures
335+
## Object
336+
An object being shared can have many attributes and subattributes and even circular references without issue. However the top/root element of data being shared **must be** an `Object` (not an array).<br>
337+
This means, sharing `arr` could be done by sharing `{arr}` and accessing it in connected_data.arr for instance.<br>
338+
339+
#### Unsupported Data Types
340+
- [NaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN)
341+
- [function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)
342+
343+
For the instances of data that will be ignored, they will simply not be shared or deleted if they were shared to be a value. Above are the instances of data that will be ignored
344+
345+
#### Supported Data Types
346+
- [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
347+
- [Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)
348+
- [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)
349+
- [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
350+
- [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
351+
- [null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null)
352+
- [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined)
353+
- [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
354+
- [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) _newly supported_
355+
- [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array)
356+
- [Uint8ClampedArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray)
357+
- [Uint16Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array)
358+
- [Uint32Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array)
359+
- [BigUint64Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigUint64Array)
360+
- [Int8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array)
361+
- [Int16Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int16Array)
362+
- [Int32Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array)
363+
- [Int64Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int64Array)
364+
- [BigInt64Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array)
365+
- [Float32Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array)
366+
- [Float64Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array)
367+
- [Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)
368+
369+
Now, the list of datatypes are listed above are supported and any other special class that isn't listed here would have its instances of data treated like a regular [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
370+
335371
## Event
336372
Let's look at what is given to `yourReaction` when you call the `addListener` function (which is a method of what is returned after calling the `serve` function)
337373
```
@@ -378,7 +414,7 @@ the value in ONE index(part) of an objToString array are 1 of the following type
378414
- data is an instance of a datatype to represent a value
379415
- refPath is an index to a referred path located in another index(part) or the path array itself
380416
- num is a number which can be 3 options: 0=not mentioned, 1=mentioned as path, 2=mentioned as reference
381-
- tag is the [Symbol.toStringTag] property of a value and is used for TypedArray, BigInt, Symbol and undefined(which has no [Symbol.toStringTag] but isn't JSON)
417+
- tag is the [Symbol.toStringTag] property of a value and is used for TypedArray, BigInt, Symbol and undefined and newly Date instances (the latter 2 which have no [Symbol.toStringTag] but isn't JSON)
382418
```
383419

384420
## Coding

for_browser.js

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,17 @@
88
const {Object,JSON,WeakMap,ReferenceError,TypeError,RangeError}=window
99
const {keys,getOwnPropertyDescriptor:describe}=Object
1010
const {stringify:str,parse}=JSON, CACHE=new WeakMap()
11+
const {toStringTag,toPrimitive}=Symbol
1112

1213

13-
14+
//determine if a value is a date or not
15+
const test_date=new Date(), test_date_num=Number(test_date)
16+
function isDate(d){
17+
return d? d[toPrimitive]?.bind(test_date)('number')===test_date_num: false;
18+
}
19+
function datesEqual(d1,d2){
20+
return d1[toPrimitive]('number')===d2[toPrimitive]('number')
21+
}
1422
//see if an enumerable property(of key) exists(in obj)
1523
function includes(obj,key){
1624
if(!obj) return false;
@@ -21,13 +29,14 @@
2129
//see if 2 objects are the "same"(to determine if to overwrite or not)
2230
function same(obj1,obj2){
2331
if(obj1===obj2) return true;
32+
if(isDate(obj1)&&isDate(obj2)&&datesEqual(obj1,obj2)) return true;
2433
if(typeof obj1==="symbol"&&typeof obj2==="symbol")
2534
return obj1.description===obj2.description;
2635
let condition1=typeof(obj1)===typeof(obj2)
2736
let condition2=(obj1 instanceof Array)===(obj2 instanceof Array)
28-
let condition3=(obj1?obj1[Symbol.toStringTag]:null) === (obj2?obj2[Symbol.toStringTag]:null)
37+
let condition3=(obj1?obj1[toStringTag]:null) === (obj2?obj2[toStringTag]:null)
2938
let conditionAll=condition1&&condition2&&condition3&&typeof obj1==="object"
30-
if(conditionAll && obj1[Symbol.toStringTag]?.includes('Array'))
39+
if(conditionAll && obj1[toStringTag]?.includes('Array'))
3140
return obj1.length===obj2.length;
3241
return conditionAll
3342
}
@@ -46,7 +55,8 @@
4655
}
4756
const nonjson={
4857
__proto__:null,
49-
undefined: function(data){return undefined},
58+
undefined: function(){return undefined},
59+
Date: function(data){return new Date(data)},
5060
Uint8Array: function(data){return new Uint8Array(data)},
5161
Uint8ClampedArray: function(data){return new Uint8ClampedArray(data)},
5262
Uint16Array: function(data){return new Uint16Array(data)},
@@ -57,6 +67,8 @@
5767
Int32Array: function(data){return new Int32Array(data)},
5868
Int64Array: function(data){return new Int64Array(data)},
5969
BigInt64Array: function(data){return new BigInt64Array(data.split(','))},
70+
Float32Array: function(data){return new Float32Array(data)},
71+
Float64Array: function(data){return new Float64Array(data)},
6072
BigInt: function(data){return BigInt(data)},
6173
Symbol: function(data){return Symbol(data)}
6274
}
@@ -69,7 +81,9 @@
6981
}
7082
function casingOf(item,forClone){
7183
if(item===undefined || item===null) return forClone? item: null;
72-
let tag=item[Symbol.toStringTag];
84+
if(isDate(item))
85+
return forClone? new Date(item[toPrimitive]('number')): item[toPrimitive]('number');
86+
let tag=item[toStringTag];
7387
if(tag){
7488
if(tag==="Symbol")
7589
return forClone? Symbol(item.description): item.description;
@@ -85,22 +99,24 @@
8599
for(let i=0;i<KEYS.length;i++){
86100
let ITEM=item[KEYS[i]]
87101
if(typeof ITEM==="bigint" || ITEM===undefined) continue;
88-
if(!ITEM || (!ITEM[Symbol.toStringTag] && typeof ITEM!=="object"))
102+
if(!ITEM || (!ITEM[toStringTag] && typeof ITEM!=="object"))
89103
shell[KEYS[i]] = ITEM;
90104
}
91105
return shell
92106
}
93107
/*
94108
the value in ONE index(part) of an objToString array are 1 of the following types:
95109
110+
[path] //delete
96111
[path,data] //value
97112
[path,refPath,num] //reference
98-
[path] //delete
113+
[path,data,0,tag] //custom datatype value
99114
100115
- path is array of strings to represent a location
101116
- data is an instance of a datatype to represent a value
102117
- refPath is an index to a referred path located in another index(part) or the path array itself
103118
- num is a number which can be 3 options: 0=not mentioned, 1=mentioned as path, 2=mentioned as reference
119+
- tag is the [Symbol.toStringTag] property of a value and is used for TypedArray, BigInt, Symbol and undefined and newly Date instances (the latter 2 which have no [Symbol.toStringTag] but isn't JSON)
104120
*/
105121
function recursivelyDetatch(map,cloned){
106122
const orig=map.get(cloned)
@@ -115,8 +131,7 @@
115131
map.delete(orig)
116132
map.delete(cloned)
117133
}
118-
function recurse(obj,clone,map,list,PATH,level,RECURSED,isTop){
119-
if(level>128) throw new RangeError("Given object goes too many levels inward (>128)");
134+
function recurse(obj,clone,map,list,PATH,RECURSED,isTop){
120135
let KEYS=keys(obj), KEYS1=keys(clone), data=map.get(obj)
121136
if(isTop) RECURSED.set(obj,true);
122137
if(obj instanceof Array){
@@ -132,14 +147,14 @@
132147
for(let i=0;i<KEYS.length;i++){
133148
let key=KEYS[i], item=obj[key]
134149
if(includes(clone,key)&&item===clone[key]) continue;
135-
if(typeof item==="function"){
150+
if(typeof item==="function"||(typeof item==="number"&&isNaN(item))){
136151
if(includes(clone,key)){
137152
delete clone[key]
138153
list.push([ [...PATH,key] ]) //delete BECAUSE datatype is function
139154
}
140155
continue;
141156
}
142-
let Path=[...PATH,key], path=data[1]<list.length&&PATH.length>=2? [data[1],key]: Path;
157+
let Path=[...PATH,key], path=data[2]>0&&(data[1]<list.length&&PATH.length>=2)? [data[1],key]: Path;
143158

144159
let notSame=!same( obj[key],clone[key] ), temp=map.get(item)
145160
if((typeof obj[key]!=="object"||!obj[key]) && (typeof clone[key]==="object"&&clone[key]))
@@ -159,11 +174,11 @@
159174
list.push([ path,refPath,mentioned ]) //refer
160175
}
161176
else{
162-
if(item===null || (item===undefined?false:!item[Symbol.toStringTag]))
177+
if(item===null || (item===undefined?false:!item[toStringTag]&&!isDate(item)))
163178
list.push([ path,casingOf(item) ]); //write
164179
else{
165180
if(item && typeof item!=="bigint") RECURSED.set(item,true);
166-
let datatype=(item||typeof item==="bigint")? item[Symbol.toStringTag]: "undefined";
181+
let datatype=(item||typeof item==="bigint")? item[toStringTag]||"Date": "undefined";
167182
list.push([ path,casingOf(item),0,datatype ]); //write(for nonjson data types)
168183
}
169184
}
@@ -177,7 +192,7 @@
177192
}
178193
if(!RECURSED.get(item)){
179194
RECURSED.set(item,true);
180-
recurse(obj[key],clone[key],map,list,Path,level+1,RECURSED);
195+
recurse(obj[key],clone[key],map,list,Path,RECURSED);
181196
}
182197
}
183198
}
@@ -195,7 +210,7 @@
195210
var {clone,map}=CACHE.get(obj)||{};
196211

197212
const list=[ [[],!map?casingOf(obj):{}] ], path=[]
198-
const tag=obj?obj[Symbol.toStringTag]||null:null
213+
const tag=obj?obj[toStringTag]||null:null
199214
if(nonjson[tag]) list[0].push(0,tag);
200215

201216
if(!map){
@@ -206,7 +221,7 @@
206221
//mentioned is if part of path was already referenced in outgoing string
207222
//0 means no(do nothing), 1 means path is mentioned in part[0], 2 means the same for part[1]
208223
map.set(obj,[path,0,1,clone,1]) //see temp description in recurse function above
209-
recurse(obj,clone,map,list,path,1,new WeakMap(),true)
224+
recurse(obj,clone,map,list,path,new WeakMap(),true)
210225
return str(list)
211226
}
212227

0 commit comments

Comments
 (0)