puleos / object-hash Goto Github PK
View Code? Open in Web Editor NEWGenerate hashes from javascript objects in node and the browser.
License: MIT License
Generate hashes from javascript objects in node and the browser.
License: MIT License
Hi,
Please how to use it on angular 2 ?
The code import {hash} from "object-hash"
trigger an error
Objects like
{ 'ключ': 'значение' }
and
{ 'ключ': 'значение1' }
Have same hash result
Hello,
Happy new year.
I encounter a slow behavior when hashing with unorderedArrays : true
with this option, the hashing take 1 second per object.
I know that a "for loop" is faster than a array.forEach,
even with map optimization can be applied :
https://jsperf.com/arraymap
https://jsperf.com/native-vs-array-js-vs-underscore/37
do you think it's possible to optimize the performance of this library ?
Regards,
Ron
Hello,
suspecting memory leaks, I ran the following test over object-hash:
const hash = require('object-hash');
console.log(process.memoryUsage());
while (true) {
const pre = Date.now();
for (let i = 0; i < 1000; i++) hash(data);
const post = Date.now();
console.log(process.memoryUsage(), "runtime: "+(post-pre)+"ms");
}
These were the results:
{ rss: 21213184, heapTotal: 10522624, heapUsed: 4672656 }
{ rss: 85860352, heapTotal: 70365184, heapUsed: 38203144 } 'runtime: 329ms'
{ rss: 118218752, heapTotal: 102469632, heapUsed: 79757256 } 'runtime: 325ms'
{ rss: 151285760, heapTotal: 135122944, heapUsed: 112984104 } 'runtime: 443ms'
{ rss: 178872320, heapTotal: 161873920, heapUsed: 126826120 } 'runtime: 513ms'
{ rss: 206196736, heapTotal: 189136896, heapUsed: 165380888 } 'runtime: 553ms'
{ rss: 244736000, heapTotal: 227192832, heapUsed: 189656008 } 'runtime: 664ms'
{ rss: 272257024, heapTotal: 254455808, heapUsed: 224160496 } 'runtime: 738ms'
{ rss: 315011072, heapTotal: 297373696, heapUsed: 263990928 } 'runtime: 812ms'
{ rss: 342827008, heapTotal: 325685248, heapUsed: 294446712 } 'runtime: 885ms'
{ rss: 370958336, heapTotal: 352948224, heapUsed: 315126088 } 'runtime: 991ms'
{ rss: 399020032, heapTotal: 381259776, heapUsed: 341713960 } 'runtime: 1107ms'
{ rss: 412856320, heapTotal: 395227136, heapUsed: 362916912 } 'runtime: 1422ms'
{ rss: 440881152, heapTotal: 422490112, heapUsed: 384875336 } 'runtime: 1213ms'
{ rss: 468836352, heapTotal: 450801664, heapUsed: 412514440 } 'runtime: 1328ms'
{ rss: 496558080, heapTotal: 478064640, heapUsed: 445826144 } 'runtime: 1412ms'
{ rss: 525045760, heapTotal: 506376192, heapUsed: 469118536 } 'runtime: 1499ms'
{ rss: 553041920, heapTotal: 533639168, heapUsed: 498784816 } 'runtime: 1632ms'
{ rss: 613945344, heapTotal: 594788352, heapUsed: 550526600 } 'runtime: 1754ms'
{ rss: 641900544, heapTotal: 623099904, heapUsed: 575188672 } 'runtime: 1862ms'
{ rss: 669708288, heapTotal: 650362880, heapUsed: 605594576 } 'runtime: 1967ms'
{ rss: 697405440, heapTotal: 677625856, heapUsed: 641817448 } 'runtime: 2096ms'
^C
Seems like the there are serious leak issues. Could you advise?
Do note that I've tried all versions 1.1.0 - 1.1.4 (inclusive).
Thanks.
Bower.json is referring to index.js
, but the right script is dist/object_hash.js
I got an error Cannot read property 'crypto' of undefined
when running on CodeSanbox.
which 'crypto' package should I install?
Symbols are unique, so the implementation added in #23 doesn't work as expected e.g.:
$ replem object-hash:hash
> s1 = Symbol("foo")
Symbol(foo)
> s2 = Symbol("foo")
Symbol(foo)
> s1 === s2
false
> o = { [s1]: "s1", [s2]: "s2" }
> o[s1] === o[s2]
false
> hash(s1) === hash(s2)
true
The last test should return false because the values are as distinct as two different numbers.
Looks like a missing polyfill.
In node.js, setTimeout and setInterval return an object that contains an object of type Timer. Would it be possible to add support for this in your library?
> t = setTimeout(console.log, 10000)
{ _idleTimeout: 10000,
_idlePrev:
{ _idleNext: [Circular],
_idlePrev: [Circular],
msecs: 10000,
ontimeout: [Function: listOnTimeout] },
_idleNext:
{ _idleNext: [Circular],
_idlePrev: [Circular],
msecs: 10000,
ontimeout: [Function: listOnTimeout] },
_idleStart: 1417567901842,
_onTimeout: [Function],
_repeat: false }
> hash(t)
[object Object]
Object
[object Timer]
Timer
Error: Unknown object type "timer"
at _object (/Users/beppu/src/github.com/ice/node_modules/object-hash/index.js:110:17)
at Object.dispatch (/Users/beppu/src/github.com/ice/node_modules/object-hash/index.js:96:48)
at /Users/beppu/src/github.com/ice/node_modules/object-hash/index.js:118:41
at Array.forEach (native)
at _object (/Users/beppu/src/github.com/ice/node_modules/object-hash/index.js:115:21)
at Object.dispatch (/Users/beppu/src/github.com/ice/node_modules/object-hash/index.js:96:48)
at hash (/Users/beppu/src/github.com/ice/node_modules/object-hash/index.js:85:31)
at objectHash (/Users/beppu/src/github.com/ice/node_modules/object-hash/index.js:32:10)
at repl:1:2
at REPLServer.self.eval (repl.js:110:21)
I'm trying to hash a JavaScript object which contains huge data including htmlelements, and it seems object-hash won't able to handle it. Also if there is recursive object, I would worry it won't able to handle it either.
I'm currently trying to use import 'object-hash/dist/object_hash.js';
to pull objectHash into my project. Unfortunately, it throws the following error:
I created a jsfiddle that shows the problem.
At a minimum, it would be ideal to resolve the current build issue. In the future, it would be really helpful if you could support the .mjs
extension in your build, such as:
https://github.com/pladaria/reconnecting-websocket/blob/master/rollup.config.js#L22
Thanks for your help.
Hi,
Just for the records, I had an issue when hashing two "same" objects. It appeared that an object order its attributes in the order they are added to it. Moreover, this hash() function will vary depending on the attribute order. It means that my two "same" objects (containing the same attributes and values) where giving a different hash.
My solution to this was to use Object.entries(myObject).sort()
like this:
// Two objects containing the same data, but differents by construction
let toto = {a: 1, b: 2};
let titi = {b: 2, a: 1};
// End up with a different hash output
console.log(hash(toto)); // AAAAAA
console.log(hash(titi)); // BBBBBB
// Let sort the attributes
toto = Object.entries(toto).sort(); // [[a, 1],[b,2]]
titi = Object.entries(titi).sort(); // [[a, 1],[b,2]]
// Same output ! :D
console.log(hash(toto)) // CCCCCC
console.log(hash(titi)) // CCCCCC
It should be possible to hash closure functions;
As an example:
function proxyFunction(function f) {
return function() {
f.apply(this, arguments);
};
}
var a = proxyFunction(function() { return 42; });
var b = proxyFunction(function() { return 23; });
assert(hash(a) === hash(b));
Even though the functions are actually different, their hash would be the same, since both would generate the string: function() { f.apply(this, arguments }
(or something similar).
At least on V8.
The best way to solve that would be hashing based on the scope: a
and b
both have a variable f
in their scope and actually use it. This variable is what makes the difference between a
and b
, so it would be cool if we could incorporate that into the hash.
Of course. JS doesn't allow this.
As a workaround with my types-and-functions
branch, the proxyFunction could store it's arguments as a property on the generated function, but that's not really nice.
I don't know how to solve this well, but maybe someone else can think of something.
I run into this funny bug in development today.
If you just do objectHash('\u00A0')
on node.js and in Chrome, the result is different.
In Chrome, the result is
>> objectHash('\u00A0')
"5edfeb46a3483b6b841f805756bc873ede319bee"
>> objectHash(' ')
"5edfeb46a3483b6b841f805756bc873ede319bee"
>> ' '.charCodeAt()
160
However, if you do the same in node.js, the result is different:
> objectHash('\u00A0')
'e97acbee3eb51eca346c892acc0b7c27b0bb6528'
> objectHash(' ')
'e97acbee3eb51eca346c892acc0b7c27b0bb6528'
> ' '.charCodeAt()
160
We are using the objectHash function to check agreement between the server copy and the client copy. It is absolutely crucial that the two gives the same result. Do you think this is a problem with crypto, or with objectHash
itself?
Please advice!
Hello,
Would it be possible to have this lib available through Bower and Client Browser ?
Please add support for base64url encoding.
see: https://www.npmjs.com/package/base64url .
Currently, all objects are sorted before hashing. This makes sense, as objects are essentially an unordered data structure.
As of ES2015 though, the spec guarantees a particular order for objects (number-like, then other strings, then symbols). See this discussion on StackOverflow.
I have a use case where the order of the object properties matters, but currently I cannot control whether the sorting happens or not. I propose adding an option unorderedObjects
, similar to unorderedSets
and unorderedArrays
, true by default.
It would be nice if URL safe base64 output is supported, which uses '-'
and '_'
instead of '+'
and '/'
.
I think md5 and sha1 are both a little long, so is there a hash generating shorter string?
Thanks.
Hey guys,
I'm getting a
Cannot read property 'crypto' of undefined
error in my Angular/Node.js project written in TypeScript. I looked in object_hash.js:1 and my guess would be it's coming from the line
r.crypto&&crypto.getRandomValues
I'm totally new to Angular and Node and have no idea how to handle this. I've "npm install"-ed both object-hash and @types/object-hash. I've uninstalled and reinstalled. No luck.
When I open a new folder somewhere else and just try hash( [1, 'hello world'], { algorithm: 'sha512' })
and logging it to the console, it seems to work just fine. There's no problem in my project until it hits the line console.log(hash([string1, string2], { algorithm: 'sha512' }));
Any help here?
I should also mention that in a previous non-Angular project, it all worked just fine. I had at the top import hash from 'object-hash';
, but now I've had to import * as hash from 'object-hash';
due to a
Module can only be default-imported using the 'allowSyntheticDefaultImports' flag
error. Please help! This might be a super-simple fix, but I have no idea how to fix this.
I originally posted this on the eslint-loader
project webpack-contrib/eslint-loader#128
Module build failed: Error: Algorithm "sha1" not supported. supported values: passthrough
at applyDefaults (/Users/chet/Code/doug/packages/doug/node_modules/object-hash/index.js:89:11)
at objectHash (/Users/chet/Code/doug/packages/doug/node_modules/object-hash/index.js:31:13)
at Object.module.exports (/Users/chet/Code/doug/packages/doug/node_modules/eslint-loader/index.js:155:20)
No idea what thats all about:
~ ❯❯❯ node --version
v6.3.1
~ ❯❯❯ node
> crypto.getHashes()
[ 'DSA',
'DSA-SHA',
'DSA-SHA1',
'DSA-SHA1-old',
'RSA-MD4',
'RSA-MD5',
'RSA-MDC2',
'RSA-RIPEMD160',
'RSA-SHA',
'RSA-SHA1',
'RSA-SHA1-2',
'RSA-SHA224',
'RSA-SHA256',
'RSA-SHA384',
'RSA-SHA512',
'dsaEncryption',
'dsaWithSHA',
'dsaWithSHA1',
'dss1',
'ecdsa-with-SHA1',
'md4',
'md4WithRSAEncryption',
'md5',
'md5WithRSAEncryption',
'mdc2',
'mdc2WithRSA',
'ripemd',
'ripemd160',
'ripemd160WithRSA',
'rmd160',
'sha',
'sha1',
'sha1WithRSAEncryption',
'sha224',
'sha224WithRSAEncryption',
'sha256',
'sha256WithRSAEncryption',
'sha384',
'sha384WithRSAEncryption',
'sha512',
'sha512WithRSAEncryption',
'shaWithRSAEncryption',
'ssl2-md5',
'ssl3-md5',
'ssl3-sha1',
'whirlpool' ]
Hello,
First off, thanks for this library! I'm interested using this library to determine whether two nested objects are structurally equal. In other words, I'd like to compare hashes computed with the excludeValues: true
option, but that takes into account whether nested objects have the same keys.
e.g.
var baz = {
foo: {
innerkey1: 'baz'
}
}
var fizz = {
foo: {
innerkey2: 'fizz'
}
}
The current behaviour has hash(baz, {excludeValues: true}) === hash(fizz, {excludeValues: true})
, but for my use case i need them to be not equal, since they have different nested keys.
If this is a use case this library would like to support I'd be interested in working on a PR for it.
Thanks
Hello,
Thank you for your work.
Would it be possible to sort the arrays ?
Currently :
var peter1 = {friends: ['Joanna', 'Michael', 'Samir'], name: 'Peter', stapler: false };
var peter2 = {friends: ['Joanna', 'Samir', 'Michael'], name: 'Peter', stapler: false }; //Different Array Order.
console.log(hash(peter1)); // result : eb23ba5f5a0ae542e37386a0cb61dd19cd616487
console.log(hash(peter2)); // result : c69f4a2b27cd0216f9d91f13689f4437c90b9c8a
When i try the below code:
const hash = require("object-hash");
console.log(hash(function () {})); // Output: 4122c3af912b486962725f2aadb66af50ada646d
console.log(hash(function () {})); // Output: 4122c3af912b486962725f2aadb66af50ada646d
Outputs are same.
I'm trying to use object-hash to hash an object containing a Mongo ObjectID.
The following code:
var ObjectID = require('mongodb').ObjectID;
var hash = require('object-hash');
console.log(hash(new ObjectID()));
Throws:
/x/node_modules/bson/lib/bson/objectid.js:347
return this.id[3] | this.id[2] << 8 | this.id[1] << 16 | this.id[0] << 24;
^
TypeError: Cannot read property '3' of undefined
at ObjectID.Object.defineProperty.get [as generationTime] (/x/node_modules/bson/lib/bson/objectid.js:347:20)
at /x/node_modules/object-hash/index.js:237:33
at Array.forEach (native)
at Object._object (/x/node_modules/object-hash/index.js:233:21)
at Object.dispatch (/x/node_modules/object-hash/index.js:183:30)
at /x/node_modules/object-hash/index.js:237:18
at Array.forEach (native)
at Object._object (/x/node_modules/object-hash/index.js:233:21)
at Object.dispatch (/x/node_modules/object-hash/index.js:183:30)
at hash (/x/node_modules/object-hash/index.js:126:10)
Any help would be greatly appreciated.
Thanks
Objects with recursive references cause an infinite recursion in the "typeHasher" function, and therefore a "maximum call stack exceeded" error. To reproduce:
var hasher = require('object-hash');
var a = {};
a.b = 5;
a.c = a;
console.log(hasher(a));
Please document that excludeValues
is set to false
by default, so people don't have to go dig in the code :)
If you could add a license file, it would help us with proper attribution. Thank you.
for(key in obj) {
...
}
{"watermark":{"position":[74,-3],"colorMode":"white","enabled":true},"subtitles":{"color":"#000000","enabled":false},"audiowave":{"size":10,"backgroundEnabled":false,"backgroundOpacity":20,"backgroundColor":"#000000","color":"#ffffff","enabled":true},"caption":{"text":"013.mp3","position":[4,8],"backgroundEnabled":true,"backgroundOpacity":36,"backgroundColor":"#000000","fontSize":40,"color":"#ffffff","enabled":true},"background":{"imageUrls":[],"enabled":false}}
===
{"watermark":{"position":[74,-3],"colorMode":"white","enabled":true},"subtitles":{"color":"#000000","enabled":false},"audiowave":{"size":10,"backgroundEnabled":false,"backgroundOpacity":20,"backgroundColor":"#000000","color":"#ffffff","enabled":true},"caption":{"text":"013.mp3","position":[4,8],"backgroundEnabled":true,"backgroundOpacity":36,"backgroundColor":"#000000","fontSize":40,"color":"#ffffff","enabled":true},"background":{"imageUrls":[],"enabled":false}}
4c44ffc6628dcedb7ee8e7c6c27c00853fcca251
!==
e7cdcdc4fad9a0e1db0517c6757236ebf1867f41
Consider:
const objectHash = require("object-hash");
objectHash(async function foo () {}); // Error: Unknown object type "asyncfunction"
This breaks usage with untranspiled code (node v7.4.0 and above as well as any ES2017+ compatible browser)
I've added a PR: #68
For auditing purposes, it would be helpful to have both the hash and the sorted object (e.g. the objects that would be hashed with setting of {unorderedArrays: true, unorderedSets: true}
).
I would contribute this option myself, but I don't think I would get it right.
Hi
I want to use it to generate access key which is publicly shared to my client when my client request using that key i can return decrypt that key and get actual result.is it possible in this ?? or any suggestion or idea to tackle this situation.
{user: {"name":"bob", cookie: 1}, cookie: 'data to skip on hashing'}
hash(data, { excludeKeys: function (key) {
return key === 'cookie';
})
will result in skipping both root cookie
and user.cookie
.
Would it be possible to add support to use the hashing as the middle-man for a key-value store?
As I see it, this would mean adding two more methods to HashTable
, namely set(key, value)
and get(key)
, where the key
is hashed. This would be particularly useful in cases when a key-value store is needed for unwieldy keys (like large Objects
, Arrays
, even perhaps Canvas images
(?), where stringifying would make things difficult).
I included the source in the html, but the object-hash object is not exposed at a global variable.
Do I have to use browserify?
Thanks!
var hasher = require('object-hash');
let t = { visitor: new String('username') };
hasher(t);
Results in:
TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be one of type string, TypedArray, or DataView. Received type object
at Hash.update (internal/crypto/hash.js:58:11)
at write (/home/user/pet/session/node_modules/object-hash/index.js:168:22)
at Object._string (/home/user/pet/session/node_modules/object-hash/index.js:303:7)
at Object._object (/home/user/pet/session/node_modules/object-hash/index.js:216:30)
at Object.dispatch (/home/user/pet/session/node_modules/object-hash/index.js:187:30)
at /home/user/pet/session/node_modules/object-hash/index.js:248:18
at Array.forEach (<anonymous>)
at Object._object (/home/user/pet/session/node_modules/object-hash/index.js:244:21)
at Object.dispatch (/home/user/pet/session/node_modules/object-hash/index.js:187:30)
at hash (/home/user/pet/session/node_modules/object-hash/index.js:128:10)
Currently, tape
is listed as a dependency
which causes unnecessary downloads. Testing libraries are usually stored under devDependencies
(which it looks like you did). Was this a mistake and should I open a PR to remove it?
Hello.
I've experienced an issue running this lib to calculate hashes inside a loop. The hash object is quiet small ~ 6 fields, containing short arrays (from 1-6 elements):
{
key: {
subkey1: ["A", "B"],
...
subkey5: ["*"]
},
type: 'sometype'
}
There are ~ 100 000 items in such array (they are coming from mongodb). If all of those keys are processed synchronously (e.g. within forEach loop)
collectionData.forEach((data) => {
...
data.hash = objectHash({key: data.key, type: data.type})
...
});
Object hash library eats ~ 100Mb heap size on each 5000 items and finally at ~60k it crashes node with error that says that there is not enough heap space left for JS.
After brief analysis memory snapshot shows that most of memory is consumed by TickObject
. I think these items are produced by event emitters that's are used inside this library.
I've write a code that's enough to fit all my needs (using ES6 features):
const crypto = require('crypto');
/**
* Sorts object fields
* @param {Object} obj Initial object
* @returns {*}
*/
const sortedObjectString = (obj) => {
if (typeof obj == 'object') {
if (Array.isArray(obj)) {
return `[${obj.sort().toString()}]`;
}
const sortedObj = new Map();
const keys = Object.keys(obj).sort();
keys.forEach((key) => {
sortedObj.set(key, sortedObjectString(obj[key]));
});
return `{${[...sortedObj].toString()}}`;
}
return obj;
};
/**
* Calculates object hash
* @param {Object} obj Object to hash
* @param {string} alg Crypto algorithm to use (default="sha256");
* @param {string=} enc Hash encoding (default="hex")
* @returns {string} Hash string
*/
const hash = (obj, alg = 'sha256', enc = 'hex') => {
const sorted = sortedObjectString(obj);
return crypto.createHash(alg)
.update(sorted)
.digest(enc);
};
I know that code above doesn't cover all features of object-hash lib, but using async collection iterator for mongodb I've managed to process all collection with object-hash, but it took 36.5s to complete and eat 563Mb of memory. My code does the same thing in 6s and using 206Mb. Without using async iterator of collection object-async fails and this code processes all collection in 2.5s using 250Mb of RAM.
There are two projects which perform almost exactly the same function as this one:
@benlaurie
https://github.com/benlaurie/objecthash
@cryptosphere
https://github.com/cryptosphere/ruby-objecthash
Between them, they support C, Go, Python, Java, and Ruby. All versions output the same SHA256 hashes for the same input and provide tests to ensure they stay that way.
It would be awesome if this library provided a compatible implementation for Javascript for e.g. verifying hashes made on the server side.
Any chance? 🎱
Hey,
did you notice anything like this? In our use-case the result hash has changed :/
I would expect objectHash(b) === objectHash(c)
for
const a = [1, 2];
const b = [[1, 2], [1, 2]];
const c = [a, a];
That's not the case. See https://codepen.io/everhardt/pen/PvYPvp for an example.
C:\Users\User\Dev\Project>bower install object-hash
bower object-hash#1.0.0 not-cached [email protected]:puleos/object-hash.git#1.0.0
bower object-hash#1.0.0 resolve [email protected]:puleos/object-hash.git#1.0.0
The authenticity of host 'github.com (192.30.252.131)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)? yes
bower ENOTFOUND Package object-hash not found
One of my dependencies, eslint-loader
uses object-hash
to retrieve hash for object { formatter: [Function], eslintPath: 'eslint' }
at https://github.com/MoOx/eslint-loader/blob/master/index.js#L172
The strange thing that for some reason internally it gets supplied with strange object for which toString
returns Object string
which causes error:
ERROR in ./src/main.js
Module build failed: TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be one of type string, TypedArray, or DataView
at Hash.update (internal/crypto/hash.js:53:11)
at write (D:\repos\js-code\cpp-tour\node_modules\object-hash\index.js:168:22)
at Object._string (D:\repos\js-code\cpp-tour\node_modules\object-hash\index.js:299:7)
at Object._object (D:\repos\js-code\cpp-tour\node_modules\object-hash\index.js:215:30)
at Object.dispatch (D:\repos\js-code\cpp-tour\node_modules\object-hash\index.js:186:30)
at D:\repos\js-code\cpp-tour\node_modules\object-hash\index.js:244:18
at Array.forEach (<anonymous>)
at Object._object (D:\repos\js-code\cpp-tour\node_modules\object-hash\index.js:240:21)
at Object.dispatch (D:\repos\js-code\cpp-tour\node_modules\object-hash\index.js:186:30)
at D:\repos\js-code\cpp-tour\node_modules\object-hash\index.js:258:23
at Array.forEach (<anonymous>)
at Object._array (D:\repos\js-code\cpp-tour\node_modules\object-hash\index.js:257:20)
at Object._object (D:\repos\js-code\cpp-tour\node_modules\object-hash\index.js:215:30)
at Object.dispatch (D:\repos\js-code\cpp-tour\node_modules\object-hash\index.js:186:30)
at D:\repos\js-code\cpp-tour\node_modules\object-hash\index.js:244:18
at Array.forEach (<anonymous>)
@ multi (webpack)-dev-server/client?http://localhost:3333 ./src/main.js
I don't entirely understand how object-hash
works but it seems to be happening due to this line https://github.com/puleos/object-hash/blob/master/index.js#L173-L175
I'm wondering is maybe some replacer used internally? As eslint-loader
itself doesn't use any options at all
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.