Skip to content

Commit

Permalink
Merge pull request #5 from Y0ursTruly/new-datatypes
Browse files Browse the repository at this point in the history
New datatype (Date) support added
  • Loading branch information
Y0ursTruly authored Sep 21, 2024
2 parents d40602d + aecc1bf commit b1d51aa
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 33 deletions.
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Share (and sync) Objects Online with the power of websockets. Keys, Values AND R
<br>
**Please note**:
- To view example usage of the modules this library provides, please refer to the _[tests](https://github.com/Y0ursTruly/webject/blob/main/tests.js)_
- Supporting the `Date` type soon. In the meantime it is advised to `Date` instances into their string or number equivalent
- Better example usages would be included later on other than the test file

# Installation
Multiple ways
Expand Down Expand Up @@ -332,6 +332,42 @@ undefined
</ul>

# Structures
## Object
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>
This means, sharing `arr` could be done by sharing `{arr}` and accessing it in connected_data.arr for instance.<br>

#### Unsupported Data Types
- [NaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN)
- [function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)

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

#### Supported Data Types
- [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
- [Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)
- [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)
- [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
- [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
- [null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null)
- [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined)
- [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
- [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) _newly supported_
- [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array)
- [Uint8ClampedArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray)
- [Uint16Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array)
- [Uint32Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array)
- [BigUint64Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigUint64Array)
- [Int8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array)
- [Int16Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int16Array)
- [Int32Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array)
- [Int64Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int64Array)
- [BigInt64Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array)
- [Float32Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array)
- [Float64Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array)
- [Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)

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)

## Event
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)
```
Expand Down Expand Up @@ -378,7 +414,7 @@ the value in ONE index(part) of an objToString array are 1 of the following type
- data is an instance of a datatype to represent a value
- refPath is an index to a referred path located in another index(part) or the path array itself
- num is a number which can be 3 options: 0=not mentioned, 1=mentioned as path, 2=mentioned as reference
- 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)
- 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)
```

## Coding
Expand Down
47 changes: 31 additions & 16 deletions for_browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,17 @@
const {Object,JSON,WeakMap,ReferenceError,TypeError,RangeError}=window
const {keys,getOwnPropertyDescriptor:describe}=Object
const {stringify:str,parse}=JSON, CACHE=new WeakMap()
const {toStringTag,toPrimitive}=Symbol



//determine if a value is a date or not
const test_date=new Date(), test_date_num=Number(test_date)
function isDate(d){
return d? d[toPrimitive]?.bind(test_date)('number')===test_date_num: false;
}
function datesEqual(d1,d2){
return d1[toPrimitive]('number')===d2[toPrimitive]('number')
}
//see if an enumerable property(of key) exists(in obj)
function includes(obj,key){
if(!obj) return false;
Expand All @@ -21,13 +29,14 @@
//see if 2 objects are the "same"(to determine if to overwrite or not)
function same(obj1,obj2){
if(obj1===obj2) return true;
if(isDate(obj1)&&isDate(obj2)&&datesEqual(obj1,obj2)) return true;
if(typeof obj1==="symbol"&&typeof obj2==="symbol")
return obj1.description===obj2.description;
let condition1=typeof(obj1)===typeof(obj2)
let condition2=(obj1 instanceof Array)===(obj2 instanceof Array)
let condition3=(obj1?obj1[Symbol.toStringTag]:null) === (obj2?obj2[Symbol.toStringTag]:null)
let condition3=(obj1?obj1[toStringTag]:null) === (obj2?obj2[toStringTag]:null)
let conditionAll=condition1&&condition2&&condition3&&typeof obj1==="object"
if(conditionAll && obj1[Symbol.toStringTag]?.includes('Array'))
if(conditionAll && obj1[toStringTag]?.includes('Array'))
return obj1.length===obj2.length;
return conditionAll
}
Expand All @@ -46,7 +55,8 @@
}
const nonjson={
__proto__:null,
undefined: function(data){return undefined},
undefined: function(){return undefined},
Date: function(data){return new Date(data)},
Uint8Array: function(data){return new Uint8Array(data)},
Uint8ClampedArray: function(data){return new Uint8ClampedArray(data)},
Uint16Array: function(data){return new Uint16Array(data)},
Expand All @@ -57,6 +67,8 @@
Int32Array: function(data){return new Int32Array(data)},
Int64Array: function(data){return new Int64Array(data)},
BigInt64Array: function(data){return new BigInt64Array(data.split(','))},
Float32Array: function(data){return new Float32Array(data)},
Float64Array: function(data){return new Float64Array(data)},
BigInt: function(data){return BigInt(data)},
Symbol: function(data){return Symbol(data)}
}
Expand All @@ -69,7 +81,9 @@
}
function casingOf(item,forClone){
if(item===undefined || item===null) return forClone? item: null;
let tag=item[Symbol.toStringTag];
if(isDate(item))
return forClone? new Date(item[toPrimitive]('number')): item[toPrimitive]('number');
let tag=item[toStringTag];
if(tag){
if(tag==="Symbol")
return forClone? Symbol(item.description): item.description;
Expand All @@ -85,22 +99,24 @@
for(let i=0;i<KEYS.length;i++){
let ITEM=item[KEYS[i]]
if(typeof ITEM==="bigint" || ITEM===undefined) continue;
if(!ITEM || (!ITEM[Symbol.toStringTag] && typeof ITEM!=="object"))
if(!ITEM || (!ITEM[toStringTag] && typeof ITEM!=="object"))
shell[KEYS[i]] = ITEM;
}
return shell
}
/*
the value in ONE index(part) of an objToString array are 1 of the following types:
[path] //delete
[path,data] //value
[path,refPath,num] //reference
[path] //delete
[path,data,0,tag] //custom datatype value
- path is array of strings to represent a location
- data is an instance of a datatype to represent a value
- refPath is an index to a referred path located in another index(part) or the path array itself
- num is a number which can be 3 options: 0=not mentioned, 1=mentioned as path, 2=mentioned as reference
- 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)
*/
function recursivelyDetatch(map,cloned){
const orig=map.get(cloned)
Expand All @@ -115,8 +131,7 @@
map.delete(orig)
map.delete(cloned)
}
function recurse(obj,clone,map,list,PATH,level,RECURSED,isTop){
if(level>128) throw new RangeError("Given object goes too many levels inward (>128)");
function recurse(obj,clone,map,list,PATH,RECURSED,isTop){
let KEYS=keys(obj), KEYS1=keys(clone), data=map.get(obj)
if(isTop) RECURSED.set(obj,true);
if(obj instanceof Array){
Expand All @@ -132,14 +147,14 @@
for(let i=0;i<KEYS.length;i++){
let key=KEYS[i], item=obj[key]
if(includes(clone,key)&&item===clone[key]) continue;
if(typeof item==="function"){
if(typeof item==="function"||(typeof item==="number"&&isNaN(item))){
if(includes(clone,key)){
delete clone[key]
list.push([ [...PATH,key] ]) //delete BECAUSE datatype is function
}
continue;
}
let Path=[...PATH,key], path=data[1]<list.length&&PATH.length>=2? [data[1],key]: Path;
let Path=[...PATH,key], path=data[2]>0&&(data[1]<list.length&&PATH.length>=2)? [data[1],key]: Path;

let notSame=!same( obj[key],clone[key] ), temp=map.get(item)
if((typeof obj[key]!=="object"||!obj[key]) && (typeof clone[key]==="object"&&clone[key]))
Expand All @@ -159,11 +174,11 @@
list.push([ path,refPath,mentioned ]) //refer
}
else{
if(item===null || (item===undefined?false:!item[Symbol.toStringTag]))
if(item===null || (item===undefined?false:!item[toStringTag]&&!isDate(item)))
list.push([ path,casingOf(item) ]); //write
else{
if(item && typeof item!=="bigint") RECURSED.set(item,true);
let datatype=(item||typeof item==="bigint")? item[Symbol.toStringTag]: "undefined";
let datatype=(item||typeof item==="bigint")? item[toStringTag]||"Date": "undefined";
list.push([ path,casingOf(item),0,datatype ]); //write(for nonjson data types)
}
}
Expand All @@ -177,7 +192,7 @@
}
if(!RECURSED.get(item)){
RECURSED.set(item,true);
recurse(obj[key],clone[key],map,list,Path,level+1,RECURSED);
recurse(obj[key],clone[key],map,list,Path,RECURSED);
}
}
}
Expand All @@ -195,7 +210,7 @@
var {clone,map}=CACHE.get(obj)||{};

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

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

Expand Down
Loading

0 comments on commit b1d51aa

Please sign in to comment.