perlin-network / life Goto Github PK
View Code? Open in Web Editor NEWA secure WebAssembly VM catered for decentralized applications.
License: MIT License
A secure WebAssembly VM catered for decentralized applications.
License: MIT License
#include <stdio.h>
#include <string.h>
#include <cstdlib>
extern "C" {
extern void logi(int);
extern void logs(char *);
extern void logl(long);
}
int main() {
int a[3];
a[0]=134;
a[1]=13;
a[2]=52;
for (const auto &item : a)
{
logi(item);
}
return 0;
}
(module
(type $FUNCSIG$vi (func (param i32)))
(import "env" "logi" (func $logi (param i32)))
(table 0 anyfunc)
(memory $0 1)
(export "memory" (memory $0))
(export "main" (func $main))
(func $main (; 1 ;) (result i32)
(local $0 i32)
(local $1 i32)
(local $2 i32)
(i32.store offset=4
(i32.const 0)
(tee_local $2
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 16)
)
)
)
(i32.store offset=12
(get_local $2)
(i32.const 52)
)
(i64.store offset=4 align=4
(get_local $2)
(i64.const 55834574982)
)
(call $logi
(i32.const 134)
)
(set_local $0
(i32.add
(i32.add
(get_local $2)
(i32.const 4)
)
(i32.const 4)
)
)
(set_local $1
(i32.const 0)
)
(loop $label$0
(call $logi
(i32.load
(i32.add
(get_local $0)
(get_local $1)
)
)
)
(br_if $label$0
(i32.ne
(tee_local $1
(i32.add
(get_local $1)
(i32.const 4)
)
)
(i32.const 8)
)
)
)
(i32.store offset=4
(i32.const 0)
(i32.add
(get_local $2)
(i32.const 16)
)
)
(i32.const 0)
)
)
=== RUN TestWasmRun
--- Begin stack trace ---
<0> [1]
--- End stack trace ---
--- FAIL: TestWasmRun (0.00s)
panic: runtime error: slice bounds out of range [recovered]
panic: runtime error: slice bounds out of range
I write a code that just printf some info. Then compile to wasm. But there is an error when run in life.
The c code:
#include <stdio.h>
int main(){
printf("test mapData1~~~~~~~~~~\r\n");
return 0;
}
The wasm
(module
(type $t0 (func (param i32) (result i32)))
(type $t1 (func (result i32)))
(import "env" "puts" (func $env.puts (type $t0)))
(func $main (export "main") (type $t1) (result i32)
(drop
(call $env.puts
(i32.const 16)))
(i32.const 0))
(table $T0 0 anyfunc)
(memory $memory (export "memory") 1)
(data (i32.const 16) "test mapData1~~~~~~~~~~\0d\00"))
the run code is:
func TestOriginLifeMap(t *testing.T){
fileCode, err := ioutil.ReadFile("./sample/test.wasm")
assert.NoError(t, err)
vm, err := exec.NewVirtualMachine(fileCode, exec.VMConfig{
EnableJIT: false,
DefaultMemoryPages: 128,
DefaultTableSize: 65536,
}, nil, nil)
assert.NoError(t,err)
entryID, ok := vm.GetFunctionExport("main")
assert.Equal(t,true,ok)
data, err := vm.Run(entryID)
assert.NoError(t,err)
fmt.Printf("the data is: %d",data)
}
There is an error:
runtime error: index out of range
I found the wasm need call "puts", but there is't the import function in ResolveFunc.
https://github.com/perlin-network/life/blob/master/main.go#L20
so does it mean life can't run the related function in c standard library?
If not, why there is an error occurred?
Hey perlin fellows,
I'm having a hard time installing your code into my machine.
I'm having this error:
λ ~/GoPath/src/github.com/perlin-network/life/ master vgo mod -vendor
go: finding github.com/losfair/wagon v0.0.0-20180807163237-f6497f251c75
go: github.com/losfair/[email protected]: unknown revision f6497f251c75d3d2ea31bdbc05b636f5d4d39221
go: error loading module requirements
m.Base.FunctionIndexSpace isn't include env functions , Crash at line 166 in module.go
gomobile bind -target=ios -o life.framework
gomobile: darwin-arm: go build -tags ios -buildmode=c-archive -o /var/folders/df/6z4dgq9d44l8164d2s4mb0r00000gn/T/gomobile-work-606257726/life-arm.a gobind failed: exit status 2
# github.com/perlin-network/life/exec
exec/vm_codegen.go:93:37: constant -9223372036854775808 overflows int
gomobile bind -target=android
gomobile: go build -buildmode=c-shared -o=/var/folders/df/6z4dgq9d44l8164d2s4mb0r00000gn/T/gomobile-work-891709332/android/src/main/jniLibs/armeabi-v7a/libgojni.so gobind failed: exit status 2
# github.com/perlin-network/life/exec
exec/vm_codegen.go:93:37: constant -9223372036854775808 overflows int
We wonder if the GC will introduce the VM pause during execution applications?
Hello all,
I am trying to run a ts (compiled with Assemblyscript) file that implements a simple function, it logs on the terminal a string concatenated with a variable (that is also a string). The code is imported through Perlin and runs in a Golang Vm.
Here is a Go code chunk that is handling the generated wasm,;-the string is reconstructed ffollowing AssemblyScript documentation on how strings are allocated in the memory(https://github.com/AssemblyScript/assemblyscript/wiki/Memory-Layout-&-Management):
ptr := int(uint32(vm.GetCurrentFrame().Locals[0]))
msgLen := int(uint32(vm.Memory[ptr]))
msg := vm.Memory[(ptr + 4):(ptr + 4 + 2*msgLen)]
fmt.Println(ptr)`
This is a ts code that when compiled works fine :
export function app_main():string{
let a = "Hello";
r.consoleLog(a);
return '0';
}
Here is another ts code that also runs without any problem:
export function app_main():string{
r.consoleLog('World');
return '0';
}
But here is a code that not only does not work but also returns an error:
export function app_main():string{
let a = 'World';
r.consoleLog("Hello"+a);
return '0';
}
And here is the error that Life returns:
Resolve func: env abort
panic: unknown field: abort
It is important to emphasize that this error does not appear in any other instances.
So, anyone has a workaround for this issue??
this is the new docker in a way.
Is there an common interop between WASM containers yet ? Wondering if GRPC is the right way to go ?
I have not even tried but raising here as i expect the team there have thought about this.
There seems to be two fundamental approaches that i see so far:
1- Open a port on the VM host that lets the VM guest use anything it wants.
2- Integrate some sort of IO API at the host level that allows VMS to talk to each other using a formalised transport.
curious where you are heading on this.
Thanks for publishing those benchmarks! I was recently looking at wabt, which among other things contains a very neat interpreter. Have you excluded it from the benchmark list on purpose (maybe wabt is too slow), or was it more due to other reasons (e.g., limited time)?
CC: @binji
Make values with disjoint lifetimes share the same storage unit.
For Gas control flow life
used AddGas
instruction.
From source code it's not clear how it injected to Wasm
instructions.
case opcodes.AddGas:
delta := LE.Uint64(frame.Code[frame.IP : frame.IP+8])
where delta
are formed?
The root question from strange behavior:
#[no_mangle]
pub extern "C" fn sum(n: u64) -> u64 {
let mut res = 0;
for x in 0..n {
res += x;
}
return res;
}
#[no_mangle]
pub extern "C" fn app_main() -> u64 {
sum(1_000_000)
}
And after execution vm.Gas == 2
. It's strange.
Memory and external calls were not counted in gas
Hello, I have my wasm module compiled (written in go) and I'm trying to load it up in the wasm vm, but following the example code doesn't work:
go: finding github.com/go-interpreter/wagon v0.0.0
# command-line-arguments
./test.go:16:35: not enough arguments in call to exec.NewVirtualMachine
have ([]byte, exec.VMConfig, *exec.NopResolver)
want ([]byte, exec.VMConfig, exec.ImportResolver, compiler.GasPolicy)
Any help would be appreciated.
Hi,
I am facing this error while trying to call a wasm file from go code:
connecto/input/src/github.com/connecto/lifecontractone/vendor/github.com/perlin-network/life/compiler/module.go:147:31: too many arguments in call to disasm.Disassemble
have (wasm.Function, *wasm.Module)
want ([]byte)
connecto/input/src/github.com/connecto/lifecontractone/vendor/github.com/perlin-network/life/compiler/module.go:151:39: cannot use d (type []disasm.Instr) as type *disasm.Disassembly in argument to NewSSAFunctionCompiler
connecto/input/src/github.com/connecto/lifecontractone/vendor/github.com/perlin-network/life/compiler/module.go:223:31: too many arguments in call to disasm.Disassemble
have (wasm.Function, *wasm.Module)
want ([]byte)
connecto/input/src/github.com/connecto/lifecontractone/vendor/github.com/perlin-network/life/compiler/module.go:227:39: cannot use d (type []disasm.Instr) as type *disasm.Disassembly in argument to NewSSAFunctionCompiler
Snippet of go code:
// Resolver defines imports for WebAssembly modules ran in Life.
type Resolver struct {
tempRet0 int64
}
// ResolveFunc defines a set of import functions that may be called within a WebAssembly module.
func (r *Resolver) ResolveFunc(module, field string) exec.FunctionImport {
fmt.Printf("Resolve func: %s %s\n", module, field)
switch module {
case "env":
switch field {
case "__life_log":
return func(vm *exec.VirtualMachine) int64 {
ptr := int(uint32(vm.GetCurrentFrame().Locals[0]))
msgLen := int(uint32(vm.GetCurrentFrame().Locals[1]))
msg := vm.Memory[ptr : ptr+msgLen]
fmt.Printf("[app] %s\n", string(msg))
return 0
}
default:
panic(fmt.Errorf("unknown field: %s", field))
}
default:
panic(fmt.Errorf("unknown module: %s", module))
}
}
// ResolveGlobal defines a set of global variables for use within a WebAssembly module.
func (r *Resolver) ResolveGlobal(module, field string) int64 {
fmt.Printf("Resolve global: %s %s\n", module, field)
switch module {
case "env":
switch field {
case "__life_magic":
return 424
default:
panic(fmt.Errorf("unknown field: %s", field))
}
default:
panic(fmt.Errorf("unknown module: %s", module))
}
}
// query callback representing the query of a chaincode
func main() {
wasmbytes, _ := getWasm(A)
entryFunctionFlag := flag.String("entry", "funcToInvoke", "entry function name")
noFloatingPointFlag := flag.Bool("no-fp", false, "disable floating point")
flag.Parse()
validator, err := wasm_validation.NewValidator()
if err != nil {
panic(err)
}
err = validator.ValidateWasm(Chaincodebytes)
if err != nil {
panic(err)
}
// Instantiate a new WebAssembly VM with a few resolved imports.
vm, err := exec.NewVirtualMachine(Chaincodebytes, exec.VMConfig{
DefaultMemoryPages: 128,
DefaultTableSize: 65536,
DisableFloatingPoint: *noFloatingPointFlag,
}, new(Resolver), nil)
if err != nil {
panic(err)
}
// Get the function ID of the entry function to be executed.
entryID, ok := vm.GetFunctionExport(*entryFunctionFlag)
if !ok {
fmt.Printf("Entry function %s not found; starting from 0.\n", *entryFunctionFlag)
entryID = 0
}
start := time.Now()
// Run the WebAssembly module's entry function.
result, err := vm.Run(entryID)
if err != nil {
vm.PrintStackTrace()
panic(err)
}
end := time.Now()
fmt.Printf("return value = %d, duration = %v\n", result, end.Sub(start))
fmt.Printf("Query Response:%s\n", result)
}
Any pointers on what might have gone wrong would be appreciated.
Thanks
package main
func main() {
s := "f64"
switch s {
case "i32":
case "i64":
case "f32":
case "f64":
default:
panic(s)
}
}
go version go1.11.1 darwin/amd64
The default branch is triggered, then panic.
It's ok in browser.
As life uses replace
section in its go.mod
, I was wondering if life works when the user tries to go-get github.com/go-interpreter/wagon
instead of github.com/perlin-network/wagon
due to lack of Go modules.
The above wasm works in nodejs
and using wagon's wasm-run
command, but running with life I get a different return value.
Calling the exported function run
with no arguments should return 4
and in nodejs
and wasm-run
it does but running under life I get 0
.
I know it's a big blob but I have not yet been able to get a smaller version that triggers the bug.
I'm trying to run stuff from the benchmarks folder just to get a sense of how things work.
In the fib_recursive
benchmark folder I ran cargo build --release
. This produced a .wasm file in the target folder. I then tried to run it with life like this:
$ ./life bench/cases/fib_recursive/target/wasm32-unknown-unknown/release/fib_recursive.wasm
panic: input too large
goroutine 1 [running]:
main.main()
/Users/jehan/life/main.go:86 +0xc29
Has anyone done it yet?
Have you guys done any testing with modules created via Go 1.11? I assume it might likely be an issue with wagon?
Simple test.go:
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello World")
}
Using Go 1.11rc1:
GOOS=js GOARCH=wasm go build -o test.wasm test.go
and then
./life -entry main /Users/gsingh/Projects/golang/src/webassembly/test.wasm
with result
panic: unexpected EOF
goroutine 1 [running]:
main.main()
/Users/gsingh/tmp/life/main.go:81 +0x72c
Maybe related to go-interpreter/wagon#69 ?
I am still going through the code to see if I can answer this myself.
Do you currently support input parameters to exported wasm functions, If so do you have an example.
I am currently stepping through vm.Run and vm.Ignite.
I want to take a snapshot of the full virtual machine state so that I can restore it possibly even on another machine (in an external function that was called during the .wasm execution).
It seems necessary to only serialize the VirtualMachine struct
for this, is this correct?
Right now, vm.Execute()
will only return every 10,000 instructions executed.
For many purposes such as metrics collection we would want to more granularly track how much instructions were executed on a single pass through a program.
func GetExport(vm *exec.VirtualMachine,name string) int64{
entryID, ok := vm.GetGlobalExport(name)
if ok {
fmt.Printf("Entry GlobalExport %s not found; starting from 0.\n", name)
entryID = 0
}
ret, err := vm.Run(entryID)
if err != nil {
vm.PrintStackTrace()
panic(err)
}
return ret
}
wagon has added module support plus made a few mods in terms of parsing custom sections.
Makes sense to stay up to date with wagon.
what is AOT shorted for?
does it necessary to compile .wasm(compile from C/rust) to in.c and out back?
In compiler/module.go
, there seems to be an initial decoder for custom sections, with the current code looking for a type of 1:
Line 52 in 57f3819
Any idea what generates these sections?
Asking because I'm adding code in my fork to decode the (LLVM 8 generated) custom section containing the function names (type = 4).
It looks like the existing code is meant to do the same thing (extract function names). Not sure what is being used to generate it though, so an curious if maybe it was from an older LLVM release or similar?
I would like to understand the benefit of transpiling WASM to an SSA-based IR
Is this solely based on the fact that register-based VM has better performance compared to a stack-based? If so, is there any benchmark showing the execution speed gain is worth the compilation overhead?
$ go get -u github.com/perlin-network/life/exec
go: finding github.com/perlin-network/life/exec latest
go: finding github.com/perlin-network/life latest
go: finding golang.org/x/tools latest
# github.com/perlin-network/life/compiler
../../../../../pkg/mod/github.com/perlin-network/[email protected]/compiler/module.go:46:23: m.Customs undefined (type *wasm.Module has no field or method Customs)
$ go version
go version go1.11 darwin/amd64
Since all code fed to the VM is guaranteed to be valid, bounds checking won't be needed.
after running go build
i get:
build github.com/perlin-network/life: cannot find module for path bytes
Full Print:
matt@ubuntu:~/web/life$ go build
go: finding github.com/go-interpreter/wagon v0.0.0
build github.com/perlin-network/life: cannot find module for path bytes
latest Go version installed on Ubuntu 16.04
Been having some issue adding Life to a project. Here is my go.mod
:
module github.com/ansermino/wasm-test
replace github.com/go-interpreter/wagon v0.0.0 => github.com/perlin-network/wagon v0.3.1-0.20180825141017-f8cb99b55a39
require (
github.com/go-interpreter/wagon v0.4.0 // indirect
github.com/perlin-network/life v0.0.0-20190402092845-c30697b41680
google.golang.org/appengine v1.5.0 // indirect
)
When I run go run
, go build
I get:
# github.com/perlin-network/life/compiler
../../../../pkg/mod/github.com/perlin-network/[email protected]/compiler/module.go:147:31: too many arguments in call to disasm.Disassemble
have (wasm.Function, *wasm.Module)
want ([]byte)
../../../../pkg/mod/github.com/perlin-network/[email protected]/compiler/module.go:151:39: cannot use d (type []disasm.Instr) as type *disasm.Disassembly in argument to NewSSAFunctionCompiler
../../../../pkg/mod/github.com/perlin-network/[email protected]/compiler/module.go:223:31: too many arguments in call to disasm.Disassemble
have (wasm.Function, *wasm.Module)
want ([]byte)
../../../../pkg/mod/github.com/perlin-network/[email protected]/compiler/module.go:227:39: cannot use d (type []disasm.Instr) as type *disasm.Disassembly in argument to NewSSAFunctionCompiler
Any plans to support new WebAssembly features?
osx high sierra, v10.13.6
A basic test of life
and the output of the go11 wasm produces the error panic: unknown module: go
.
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ export PATH=/usr/local/go1.11.1/bin:$PATH
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ go version
go version go1.11.1 darwin/amd64
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ GOARCH=wasm GOOS=js go build -o lib.wasm m.go
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ ls -alFtr|tail
drwxrwxr-x 3 jaten staff 96 Oct 22 22:39 spec/
drwxrwxr-x 14 jaten staff 448 Oct 22 22:39 tests/
drwxrwxr-x 3 jaten staff 96 Oct 22 22:39 utils/
drwxrwxr-x 13 jaten staff 416 Oct 22 22:39 .git/
-rw-rw-r-- 1 jaten staff 350 Oct 22 22:40 go.sum
drwxrwxr-x 4 jaten staff 128 Oct 22 22:40 vendor/
-rwxrwxr-x 1 jaten staff 3496456 Oct 22 22:40 test_runner*
-rw-rw-r-- 1 jaten staff 177 Oct 22 22:44 m.go
-rwxrwxr-x 1 jaten staff 2532371 Oct 22 22:44 lib.wasm*
drwxrwxr-x 22 jaten staff 704 Oct 22 22:44 ./
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ life ./lib.wasm
Resolve func: go debug
panic: unknown module: go
goroutine 1 [running]:
main.main()
/Users/jaten/go/src/github.com/perlin-network/life/main.go:78 +0x63d
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ cat m.go
package main
import (
"fmt"
"time"
)
func main() {
t0 := time.Now()
a := 0
for i := 0; i < 10000000; i++ {
a++
}
fmt.Printf("a = %v, elap=%v\n", a, time.Since(t0))
}
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ go run m.go # positive control
a = 10000000, elap=2.941357ms
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ git log|head
commit 4e2637791edc5716293a29710531e36d39da4d5c
Merge: 1eb3d14 6525bd2
Author: Heyang Zhou <[email protected]>
Date: Fri Oct 12 11:18:30 2018 +0800
Merge pull request #38 from perlin-network/return-on-gas-limit
Allow normal return instead of error when gas limit is exceeded.
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $
could GasPolicy have more detail abount op like below
type GasPolicy interface {
GetCost(key Instr) int64
}
some time more detail may be needed
eg:
GrowMemory op. i want to know how many pages to grow, op gas may be n* pageGas.
if think it ok. i can have a pr
Current there is an example for read string in resolvefunction, how about return a string? In my mind, we need two methods return pointer and len respect, however how to combined these operation in two methods call?
I encountered an error while executing the go mod vendor download dependency. I tried Google and found no answer. Who can tell me how to solve this problem?
go: labix.org/v2/[email protected]: bzr pull --overwrite-tags in /Users/residuallaugh/go/pkg/mod/cache/vcs/ca61c737a32b1e09a0919e15375f9c2b6aa09860cc097f1333b3c3d29e040ea8: exit status 3: bzr: ERROR: Not a branch: "/Users/residuallaugh/go/pkg/mod/cache/vcs/ca61c737a32b1e09a0919e15375f9c2b6aa09860cc097f1333b3c3d29e040ea8/.bzr/branch/": location is a repository. go: finding launchpad.net/gocheck v0.0.0-20140225173054-000000000087 go: launchpad.net/[email protected]: bzr pull --overwrite-tags in /Users/residuallaugh/go/pkg/mod/cache/vcs/f46ce2ae80d31f9b0a29099baa203e3b6d269dace4e5357a2cf74bd109e13339: exit status 3: bzr: ERROR: Not a branch: "/Users/residuallaugh/go/pkg/mod/cache/vcs/f46ce2ae80d31f9b0a29099baa203e3b6d269dace4e5357a2cf74bd109e13339/.bzr/branch/": location is a repository. go: error loading module requirements
This project looks great and I'd love to use it for an upcoming project.
Unfortunately, it just won't work:
➜ go get
go: finding github.com/perlin-network/life/exec latest
go: finding github.com/perlin-network/life latest
go: finding github.com/go-interpreter/wagon v0.0.0
go: github.com/go-interpreter/[email protected]: unknown revision v0.0.0
go: error loading module requirements
Is there a workaround or should I just wait for stability?
extern void get(char *);
int add() {
char aa[100];
get(aa);
return 0;
}
When using go mod vendor
:
go: finding github.com/perlin-network/life latest
go: finding github.com/go-interpreter/wagon v0.0.0
go: github.com/go-interpreter/[email protected]: unknown revision v0.0.0
go: error loading module requirements
I'm on go version go1.11.5 linux/amd64
. (This might be my fault- I've never used go modules before.)
Thanks for any help!
Will be nice to have a docker file to simplify testing of ./life binary.
// Execute starts the virtual machines main instruction processing loop.
// This function may return at any point and is guaranteed to return
// at least once every 10000 instructions. Caller is responsible for
// detecting VM status in a loop.
As far as I can tell, this is just not true. It only returns on exit/error or gas limit exceeded. And a trivial infinite loop (jmp
over and over) never triggers the gas limit check. This means there is no way to prevent a VM from being tied up forever by an infinite loop.
Can you provide an example of how to invoke a process in your VM with instruction step limits?
Can instruction steps and memory usage be limited separately?
What is the granularity of resource control (for time: the number of milliseconds or with Instruction steps: per instruction, per block, per function call; for memory: bytes, kilobytes, pages, etc.)?
Is it possible to refuel a process that ran out of gas?
Can a process within your VM create and sandbox another one? (Either by a custom VM instruction or providing an external function that the process can call)
I am trying to implement the invoke_ii
helper for emscripten. The JS generated by emscripten is:
function invoke_ii(index,a1) {
var sp = stackSave();
try {
return Module["dynCall_ii"](index,a1);
} catch(e) {
stackRestore(sp);
if (typeof e !== 'number' && e !== 'longjmp') throw e;
Module["setThrew"](1, 0);
}
}
stackSave
, stackRestore
, and dynCall_ii
all ultimately come from the WASM and the call here is just a shim (I assume to enable using JS exceptions for some handling here? Not 100% sure why emscripten needs this shim). When I try to just find dynCall_ii
and use vm.Run
however, I get call stack not empty; cannot ignite
-- is it just not possible to call back into WASM from the go side at the moment, or am I missing some way to do this?
Hey Perlin guys:
In "Features" section, I saw "JIT support for x86-64 and ARM is planned". But In "Benchmarks" section, I saw the test result of life(JIT). So what's the current status of life's jit compiler?
Thanks!
Hey Perlin fellows,
How are you doing?
I would like to know how your Strings support works (if you have it)!
Right now the resolver can only return int64
for globals.
# github.com/perlin-network/life/compiler
src/github.com/perlin-network/life/compiler/module.go:115:8: e.Kind undefined (type *wasm.ImportEntry has no field or method Kind)
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.