-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclone.js
More file actions
85 lines (77 loc) · 5.08 KB
/
Copy pathclone.js
File metadata and controls
85 lines (77 loc) · 5.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//
// Copyright (c) Sebastian Kucharczyk <kuchen@kekse.biz>
// https://kekse.biz/ https://github.com/kekse1/javascripts/
// v0.7.0
//
// Just a tiny function to *really* clone objects (etc.); .. with all types, not only JSON supported ones
// or so (sometimes the web referes to just `JSON.parse(JSON.stringify({}))`);
//
// If you really start with an own `Map` instance (2nd parameter), you can even define to replace any
// occurence of some object with your own values. Functions are also cloned, if not native ones or
// `_function` argument is `false` (including all of their members, if any additional are defined under 'em).
//
// If an object got an own `.clone()` function, it will be used; and the same for the well-known `.cloneNode()`
// function of any `Node` in the browser.
//
//
const DEFAULT_CLONE_FUNCTION = false;
//
const isTypedArray = (_item) => { var result;
try { result = _item.constructor.__proto__.name;
result = (result === 'TypedArray'); }
catch(_err) { result = false; }
return result; };
// i really do *not* want `instanceof` (see 'reflection.js'):
const is = (_item, _type) => { if(typeof _type !== 'string') _type = null;
var result; try { result = _item.constructor.name; }
catch(_err) { if(_type !== null) return false; return ''; }
if(_type !== null) return (result === _type); return result; };
const isDate = (_item) => is(_item, 'Date');
const checkForMapAndSetTypes = (_item) => { const type = is(_item);
if(!type) return null; switch(type) {
case 'Map': case 'Set': case 'WeakMap': case 'WeakSet': return type; }
return null; };
//
Reflect.defineProperty(Reflect, 'clone', { value: (_object, _map = null, _function = DEFAULT_CLONE_FUNCTION, ... _clone_args) => {
if(!_map) _map = new Map(); else if(_map.has(_object)) return _map.get(_object); var result;
var chk = checkForMapAndSetTypes(_object); if(chk) { switch(chk) {
case 'Map': result = new Map(_object); break;
case 'Set': result = new Set(_object); break;
case 'WeakMap': result = new WeakMap(_object); break;
case 'WeakSet': result = new WeakSet(_object); break; }
_map.set(_object, result); return result; }
if(isDate(_object)) { result = new Date(_object); _map.set(_object, result); return result; }
if(isTypedArray(_object)) { result = _object.slice(); _map.set(_object, result); return result; }
if(!Reflect.isExtensible(_object)) { _map.set(_object, _object); return _object; }
if(typeof _object === 'undefined' || _object === null) return _object; const keys = Reflect.ownKeys(_object);
var cloneFunc; if(typeof _object.clone === 'function') cloneFunc = _object.clone.bind(_object, ... _clone_args); else if(typeof _object.cloneNode === 'function')
cloneFunc = _object.cloneNode.bind(_object, true, ... _clone_args); else cloneFunc = null; if(cloneFunc === null && !Reflect.isExtensible(_object)) {
_map.set(_object, _object); return _object; } const isArray = (cloneFunc !== null ? -1 : (Array.isArray(_object) ?
_object.length : -1)); var result; if(cloneFunc !== null) { result = cloneFunc(); _map.set(_object, result); return result; }
else if(isArray > -1) { result = new Array(isArray); for(var i = 0; i < _object.length; ++i) { keys.remove(i.toString()); result[i] = Reflect.clone(_object[i], _map, _function,
... _clone_args); keys.remove('length'); }} else if(typeof _object === 'function') { if(Function.isNative(_object) || !_function) result = _object;
else try { eval('result = ' + _object.toString()); } catch(_error) { result = _object; } keys.remove('length', 'name', 'arguments', 'caller', 'prototype'); }
else if(Object.isNull(_object)) result = Object.create(null); else try { result = Object.create(Reflect.getPrototypeOf(_object)); }
catch(_error) { result = {}; } _map.set(_object, result); _map.set(result, result); var desc; for(var i = 0; i < keys.length; ++i) {
try { desc = Reflect.getOwnPropertyDescriptor(_object, keys[i]);
if('value' in desc) { desc.value = Reflect.clone(desc.value, _map, _function, ... _clone_args); delete desc.get; delete desc.set; }
else { if(typeof desc.get === 'function') desc.get = Reflect.clone(desc.get, _map, _function, ... _clone_args); else delete desc.get;
if(typeof desc.set === 'function') desc.set = Reflect.clone(desc.set, _map, _function, ... _clone_args); else delete desc.set; }
} catch(_err) { desc = { value: _object[keys[i]] }; } Reflect.defineProperty(result, keys[i], desc); } return result; }});
Reflect.defineProperty(Object, 'clone', { value: Reflect.clone });
//
Reflect.defineProperty(Function, 'isNative', { value: (... _args) => {
if(_args.length === 0) return null;
else for(var i = 0; i < _args.length; ++i) if(typeof _args[i] !== 'function') return false;
else if(!_args[i].toString().endsWith(Function.isNative.compareString)) return false; return true;
}});
Function.isNative.compareString = '() { [native code] }';
//
Reflect.defineProperty(Object, 'isNull', { value: (... _args) => {
if(_args.length === 0) return null;
else for(var i = 0; i < _args.length; ++i) {
if(typeof _args[i] !== 'object' || _args[i] === null) return false;
else if(Reflect.getPrototypeOf(_args[i]) !== null) return false; }
return true;
}});
//