Giter Club home page Giter Club logo

v7's Introduction

V7: Embedded JavaScript engine

NOTE: this project is deprecated in favor of https://github.com/cesanta/mjs

License

V7 is the smallest JavaScript engine written in C. V7 features are:

  • Cross-platform: works on anything, starting from Arduino to MS Windows
  • Small size. Compiled static size is in 40k - 120k range, RAM footprint on initialization is about 800 bytes with freeze feature, 15k without freeze feature
  • Simple and intuitive C/C++ API. It is easy to export existing C/C++ functions into JavaScript environment
  • Standard: V7 implements JavaScript 5.1
  • Usable out-of-the-box: V7 provides an auxiliary library with Hardware (SPI, UART, etc), File, Crypto, Network API
  • Source code is both ISO C and ISO C++ compliant
  • Very easy to integrate: simply copy two files: v7.h and v7.c into your project

V7 makes it possible to program Internet of Things (IoT) embedded devices in JavaScript. V7 is a part of the full stack Mongoose OS Platform.

Examples & Documentation

Contributions

To submit contributions, sign Cesanta CLA and send GitHub pull request. You retain the copyright on your contributions.

Licensing

V7 is released under commercial and GNU GPL v.2 open source licenses.

Commercial Projects: Once your project becomes commercialised GPLv2 licensing dictates that you need to either open your source fully or purchase a commercial license. Cesanta offer full, royalty-free commercial licenses without any GPL restrictions. If your needs require a custom license, we’d be happy to work on a solution with you. [Contact us for pricing.] (https://www.cesanta.com/contact)

Prototyping: While your project is still in prototyping stage and not for sale, you can use V7’s open source code without license restrictions.

v7's People

Contributors

alashkin avatar cpq avatar dimonomid avatar edvakf avatar evthewolf avatar giannitedesco avatar grodansparadis avatar headler avatar imax9000 avatar mattn avatar mwanna avatar novlean avatar rojer avatar ruslanvaliullin avatar timgates42 avatar vrz avatar vstakhov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

v7's Issues

weird syntax errors

tests\v7_basic_test.js line 59: syntax error

tests\run_ecma262_tests.js line 27: syntax error

Regression in 32bit build

Regression introduced in 738b340:

$ make -C tests test_m32 CFLAGS_EXTRA="-DV7_ENABLE_COMPACTING_GC" TEST_FILTER=ecma
CC      unit_test_m32
RUN     unit_test_m32 ecma
make: *** [test_m32] Segmentation fault: 11

Uninitialized memory String split

mkm@santa $ docker run --rm -v $PWD/..:/cesanta -t -i --entrypoint=/bin/bash cesanta/v7_test -c "cd /cesanta/v7; make -C tests test_msan CFLAGS_EXTRA='-DV7_ENABLE_GCx' TEST_FILTER="
make: Entering directory `/cesanta/v7/tests'
CC      unit_test_msan
RUN     unit_test_msan
==32== WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x7f4b41d62335 in chartorune /cesanta/v7/tests/../src/utf.c:56
    #1 0x7f4b41d96ff7 in unescape /cesanta/v7/tests/../src/vm.c:722
    #2 0x7f4b41d97849 in embed_string /cesanta/v7/tests/../src/vm.c:748
    #3 0x7f4b41d89c61 in v7_create_string /cesanta/v7/tests/../src/vm.c:777
    #4 0x7f4b41d7f0b7 in Str_split /cesanta/v7/tests/../src/string.c:500
    #5 0x7f4b41dda825 in i_eval_call /cesanta/v7/tests/../src/interpreter.c:887
    #6 0x7f4b41dd4a44 in i_eval_expr /cesanta/v7/tests/../src/interpreter.c:604
    #7 0x7f4b41dd59a9 in i_eval_expr /cesanta/v7/tests/../src/interpreter.c:646
    #8 0x7f4b41dc9bf8 in i_eval_stmt /cesanta/v7/tests/../src/interpreter.c:1355
    #9 0x7f4b41dc06b3 in i_eval_stmts /cesanta/v7/tests/../src/interpreter.c:966
    #10 0x7f4b41dc2929 in i_eval_stmt /cesanta/v7/tests/../src/interpreter.c:993
    #11 0x7f4b41dc11fc in v7_exec_with /cesanta/v7/tests/../src/interpreter.c:1447
    #12 0x7f4b41dc9ead in v7_exec /cesanta/v7/tests/../src/interpreter.c:1461
    #13 0x7f4b41d5d42b in test_ecmac /cesanta/v7/tests/unit_test.c:1039
    #14 0x7f4b41d1aec4 in run_all_tests /cesanta/v7/tests/unit_test.c:1777
    #15 0x7f4b41d1964c in main /cesanta/v7/tests/unit_test.c:1788
    #16 0x7f4b40b8fec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
    #17 0x7f4b41d193cc in _start (/cesanta/v7/tests/unit_test_msan+0x7a3cc)

SUMMARY: MemorySanitizer: use-of-uninitialized-value /cesanta/v7/tests/../src/utf.c:56 chartorune
Exiting

v7_to_string() returns string pointers which cannot be passed to routines that expects null terminated strings

I see that V7 strings are not null-terminated by design...

A lot of C libraries does not support API to work with non-nullterminated strings. That means the developer need to make a copy of string returned by v7_to_string() and add termination symbol before passing it to some library routine. E.g. sqlite_open() API expects null terminated strings passed as parameters. The approach when you need to make a temporary copy of string looks not handy to me and leads to unnecessary memory allocations when developing custom interfaces against different 3rdparty libraries.

I believe that adding termination symbol to strings will not seriously increase the memory consumption but it will make the library's API easy to link with other libraries and develop custom interfaces. At least, there could be preprocessor option to add or not to add the termination symbol, but I would not recommend to proceed with such way, because different implemented custom interfaces (released by different developers) may require different options and it will not be possible to link them alltogether.

Sorry, if current design is something like a key feature in your library - just close my issue in this case. If not - I could probably help to you with that.

Stack corruption(?) related to introspection on 32-bit.

I discovered this as I was examining the environment to see if v7 would be usable for a project I am working on.

The example program here is to iterate over objects recursively and print out information on them. It behaves differently on 32-bit and 64-bit.

FYI, initially I discovered this on 32-bit ARM, but it also appears on i386.

function printobj(objname, object, indent) 
{
    var __ind = "";
    for (var __i=0; __i < indent; ++__i) {
        __ind = __ind + "  ";
    }

    for (name in object) {
                var val = object[name];
                var oname = name;

            if (name != undefined && val != undefined && typeof val === "object" &&  name != "global") {
                    print(__ind + name + " = {" );
                printobj(name, val, indent+1);
                    print(__ind + "}  // " + oname);
            } else if (name != "global")  {
                    print(__ind + name + " : " + val + " : " + typeof val );
                }
    }
}

printobj("this", this, 0);


I apologize for my crappy Javascript code and ignorance of how to test if something is undefined or not.

On a 32-bit machine, the output is as follows:

"printobj : [function printobj(objname,object,indent){var __ind,__i,val,oname}] : function"
"Function : cfunc_0x80683cb : function"
"JSO = {"
"}  // JSON"
"Number = {"
"}  // Number"
"String : cfunc_0x804de65 : function"
"Mat = {"
"  SQRT2 : 1.41421 : number"
"  SQRT1_2 : 0.707107 : number"
"  LOG10E : 0.434294 : number"
"  LOG2E : 1.4427 : number"
"  LN10 : 2.30259 : number"
"  L : 0.693147 : number"
"  P : 3.14159 : number"
"  E : 2.71828 : number"
"  t : cfunc_0x804d6c5 : function"
"  sqrt : cfunc_0x804d684 : function"
"  s : cfunc_0x804d643 : function"
"  round : cfunc_0x804d602 : function"
"  random : cfunc_0x804d706 : function"
"  p : cfunc_0x804d5c1 : function"
"  m : cfunc_0x804d827 : function"
"  m : cfunc_0x804d868 : function"
"  l : cfunc_0x804d580 : function"
"  floor : cfunc_0x804d53f : function"
"  e : cfunc_0x804d4fe : function"
"  c : cfunc_0x804d4bd : function"
"  ceil : cfunc_0x804d47c : function"
"  atan2 : cfunc_0x804d43b : function"
"  atan : cfunc_0x804d3fa : function"
"  asin : cfunc_0x804d3b9 : function"
"  acos : cfunc_0x804d378 : function"
"  a : cfunc_0x804d337 : function"
"}  // Math"
"Boolean : cfunc_0x804cdaa : function"
"RangeError : [function RangeError(m)] : function"
"InternalError : [function InternalError(m)] : function"
"ReferenceError : [function ReferenceError(m)] : function"
"SyntaxError : [function SyntaxError(m)] : function"
"TypeError : [function TypeError(m)] : function"
"Err : [function Error(m)] : function"
"Arr : cfunc_0x804aff3 : function"
"Object : [function Object(v)] : function"
"Infinity : Infinity : number"
"Fil = {"
"  write : cfunc_0x806926d : function"
"  read : cfunc_0x8069102 : function"
"  close : cfunc_0x8069387 : function"
"  open : cfunc_0x806941c : function"
"}  // File"
"loa : cfunc_0x806905f : function"
"base64_decode : cfunc_0x8068fad : function"
"base64_encode : cfunc_0x8069006 : function"
"exi : cfunc_0x8068b2e : function"
"eva : cfunc_0x80689c9 : function"
"pri : cfunc_0x8068880 : function"
undefined

Notice how the names start to lose the last letters of their names. e.g., "JSO" instead of "JSON". I would think it was just the last letter, but the last one, "print", has become just "pri".

On a 64-bit machine, however, the output is correct.

"printobj : [function printobj(objname,object,indent){var __ind,__i,val,oname}] : function"
"Function : cfunc_0x41f34e : function"
"JSON = {"
"}  // JSON"
"Number = {"
"}  // Number"
"String : cfunc_0x406007 : function"
"Math = {"
"  SQRT2 : 1.41421 : number"
"  SQRT1_2 : 0.707107 : number"
"  LOG10E : 0.434294 : number"
"  LOG2E : 1.4427 : number"
"  LN10 : 2.30259 : number"
"  LN2 : 0.693147 : number"
"  PI : 3.14159 : number"
"  E : 2.71828 : number"
"  tan : cfunc_0x405a20 : function"
"  sqrt : cfunc_0x4059f2 : function"
"  sin : cfunc_0x4059c4 : function"
"  round : cfunc_0x405996 : function"
"  random : cfunc_0x405a4e : function"
"  pow : cfunc_0x405968 : function"
"  min : cfunc_0x405b72 : function"
"  max : cfunc_0x405ba0 : function"
"  log : cfunc_0x40593a : function"
"  floor : cfunc_0x40590c : function"
"  exp : cfunc_0x4058de : function"
"  cos : cfunc_0x4058b0 : function"
"  ceil : cfunc_0x405882 : function"
"  atan2 : cfunc_0x405854 : function"
"  atan : cfunc_0x405826 : function"
"  asin : cfunc_0x4057f8 : function"
"  acos : cfunc_0x4057ca : function"
"  abs : cfunc_0x40579c : function"
"}  // Math"
"Boolean : cfunc_0x405327 : function"
"RangeError : [function RangeError(m)] : function"
"InternalError : [function InternalError(m)] : function"
"ReferenceError : [function ReferenceError(m)] : function"
"SyntaxError : [function SyntaxError(m)] : function"
"TypeError : [function TypeError(m)] : function"
"Error : [function Error(m)] : function"
"Array : cfunc_0x403ab1 : function"
"Object : [function Object(v)] : function"
"Infinity : Infinity : number"
"File = {"
"  write : cfunc_0x4202e7 : function"
"  read : cfunc_0x4201d9 : function"
"  close : cfunc_0x4203ce : function"
"  open : cfunc_0x42042c : function"
"}  // File"
"load : cfunc_0x420158 : function"
"base64_decode : cfunc_0x4200da : function"
"base64_encode : cfunc_0x420119 : function"
"exit : cfunc_0x41fa07 : function"
"eval : cfunc_0x41f8b1 : function"
"print : cfunc_0x41f78e : function"
undefined

Here it seems more like what you would expect. Names are not corrupted.

`-Os` optimizer on amalgamated sources exposes a bug

On clang OSX:

mkm@santa $ make -C tests unit_test-ansi V=1 CFLAGS_EXTRA="-Os" && (cd tests; time ./unit_test_ansi inter) 
CC      unit_test_ansi
cc -pedantic -ansi /Users/mkm/Projects/cesanta/v7/tests/unit_test.c ../v7.c -o unit_test_ansi -W -Wall -Wno-comment -Wno-variadic-macros -g -O0 -I../src -I. -DV7_EXPOSE_PRIVATE  -Os -finline -lm
Fail on line 1225: [v7_exec(v7, &v, "(function(){try {throw new Error}catch(e){c=e}})();c instanceof Error") == V7_OK]

With explicit -fno-inline the test passes.
Explicit -finline on other optimization levels also doesn't expose the bug.

Regression has been introduced in 559ee4a although it doesn't seem that that particular code is ever touched by that particular test.

Design & implement AST generation

V7 should be a 2-pass engine:
Source code -> parsing -> AST -> execution
That is beneficial for functionality separation, future code generation, and performance.

Compiler optimization exposes a bug in exception handling

$ make v7 CFLAGS_EXTRA='-O3'
$ ./v7 -e 'ca=0;fin=0;try{try{xxxx}finally{fin=1}}catch(e){ca=1};[fin,ca]'
[1,0]

While:

$ make v7 CFLAGS_EXTRA='-O1'
$ ./v7 -e 'ca=0;fin=0;try{try{xxxx}finally{fin=1}}catch(e){ca=1};[fin,ca]'
[1,1]

-Os, -O2, -O3 expose the bug, while -O0 and -O1 produce the correct output.

Improve build and test experience for developers using windows

Developers having only windows machines and who are not repository owners (or even if they are, they are using personal forks of the v7 repo) cannot currently easily check whether their changes break a build.

make docker, (with boot2docker) is an easy way to reproduce our build, but we need a couple of tweaks in the makefile to make it work seamlessly on windows.

Strange Output from Basic Strings

I was just experimenting with v7 and right off of the bat, I am seeing some strange behavior from some pretty basic source. Additionally, small differences have a wide variety:

A missing first character

"use strict";

var firstName = "net",
    lastName  = "poetica";

function fullName(){
  return (firstName + " " + lastName);
}

print(fullName());

Output:

➜  v7 git:(master) ./v7 test.js
"et poetica"

Strange characters & variable name appears in string (when not using print()) - additionally, different strings behave differently - i.e. if you use "net" and "poetica" in this next piece of code, you get same output as previous example.

"use strict";

var firstName = "Keith",
    lastName  = "Rosenberg";

function fullName(){
  return (firstName + " " + lastName);
}

fullName();

Output:

➜  v7 git:(master) ./v7 test.js
"ith astNa�L�)�Rosenberg"

Double last-name

var firstName = "Keith",
    lastName  = "Rosenberg";

function fullName(){
  return (firstName + " " + lastName);
}

fullName();

Output:

➜  v7 git:(master) ./v7 test.js
"ith RosenbergRosenber"

Any idea what might be causing this type of behavior? Some system info if it helps:

Darwin Kernel Version 13.4.0: Sun Aug 17 19:50:11 PDT 2014; root:xnu-2422.115.4~1/RELEASE_X86_64 x86_64

And the output from Make:

➜  v7 git:(master) make
/usr/bin/clang /Users/rosenbek/Desktop/git/v7/src/mbuf.c /Users/rosenbek/Desktop/git/v7/src/utf.c /Users/rosenbek/Desktop/git/v7/src/varint.c /Users/rosenbek/Desktop/git/v7/src/tokenizer.c /Users/rosenbek/Desktop/git/v7/src/array.c /Users/rosenbek/Desktop/git/v7/src/boolean.c /Users/rosenbek/Desktop/git/v7/src/math.c /Users/rosenbek/Desktop/git/v7/src/ast.c /Users/rosenbek/Desktop/git/v7/src/vm.c /Users/rosenbek/Desktop/git/v7/src/parser.c /Users/rosenbek/Desktop/git/v7/src/interpreter.c /Users/rosenbek/Desktop/git/v7/src/slre.c /Users/rosenbek/Desktop/git/v7/src/object.c /Users/rosenbek/Desktop/git/v7/src/error.c /Users/rosenbek/Desktop/git/v7/src/main.c -o v7 -DV7_EXE -DV7_EXPOSE_PRIVATE -W -Wall -pedantic -Wno-comment -Wno-variadic-macros -g -O0 -lm  -I./src -I.  -lm
/usr/bin/clang v7.c -o amalgamated_v7 -DV7_EXE -DV7_EXPOSE_PRIVATE -W -Wall -pedantic -Wno-comment -Wno-variadic-macros -g -O0 -lm  -I./src -I.  -lm
CLEAN   coverage
CLEAN   all
CC  unit_test_ansi
CC  unit_test_c99
CC  unit_test_c11
../v7.c:4183:10: warning: ISO C90 forbids mixing declarations and code [-Wdeclaration-after-statement]
  size_t n = vsnprintf(buf, size, fmt, ap);
         ^
1 warning generated.
CC  unit_test_ansi
../v7.c:4183:10: warning: ISO C90 forbids mixing declarations and code [-Wdeclaration-after-statement]
  size_t n = vsnprintf(buf, size, fmt, ap);
         ^
1 warning generated.
RUN unit_test_ansi 
ECMA tests coverage: 43.25%
PASS, tests run: 23919
CC  unit_test_c99
RUN unit_test_c99 
ECMA tests coverage: 43.25%
PASS, tests run: 23919
CC  unit_test_c11
RUN unit_test_c11 
ECMA tests coverage: 43.25%
PASS, tests run: 23919

Create VM values for raw pointers

What is the plan for an API to create VM values for raw pointers? I see v7_to_foreign() but there is no correspond v7_create_foreign(). Looking at the source code I found v7_pointer_to_value() - is this something that going to be a public? In the same time I see comment:
/* NOTE(lsm): don't use v7_pointer_to_value, 32-bit ptrs will truncate */

Please let me know if this is not an appropriate place to put my questions...

Update: It looks like the only way is using v7_create_number(v7, (unsigned long) some_ptr) I can pass raw pointers to VM. My concern is that there is no way to add a destructor function which will be called when VM value GCeed...

Implement Crypto interface

There is src/crypto.c which uses old internal V7 API. Please port:

  • Port Crypto.md5() and Crypto.md5_hex()
  • Port Crypto.sha1() and Crypto.sha1_hex()

problem with short strings

v7 -e "print('12345')"
"123"

v7 -e "print('123' + '45')"
"123"

need to correct in vm.c:
v7_create_string()
s_concat()

too deep stack

В parse_expression вызывается parse_logical_or, в которую, в свою очередь, как в матрёшку вложены остальные парсеры: parse_logical_and->parse_bitwise_or->parse_bitwise_xor->etc.
Спору нет, красивое решение.
Но, при использовании во встроенных системах может возникнуть проблема из-за слишком глубокого стека. Может банально не хватить памяти. Ведь место под стек чаще всего выделяется статически и отхватив его слишком много можно обделить всё остальное.
IMHO, правильнее было бы вызывать все парсеры из parse_expression на одном уровне вложенности.

Date from string assumes null terminated strings

V7 strings are defined as ptr+len pairs, i.e v7_to_strings thus return a non null-terminated string.

d_timeFromString accepts a string+len but then from there on it treats the string as null terminated.

Probably we should document this behaviour better, so that new contributors don't trip over this.

Constructors don't work with the 'new' operator

For example, the line:

v7.exe -e "var s = new String ('aaa'); print (s);"

yields this:

Assertion failed: v7-> root_scope.proto == & s_global, file v7.c, line 1379

This gets in the way while debugging methods of the String object.
Could you please do something with it?

flag called_as_constructor

при вызове функции используется struct v7_c_func_arg, в которой присутствует флаг called_as_constructor.
Этот флаг приходится анализировать во всех функциях конструкторах и в зависимости от него работать с cfa->this_obj или с cfa->result.
Не проще ли перед вызовом конструктора приравнять result = this_obj;
А в тех(более редких) ситуациях, когда функции всё-таки нужно знать что она вызвана как конструктор можно это проверять так: if(cfa->result == cfa->this_obj).

Macros

TRACE_OBJ, MKOBJ, SET_RO_PROP_V, SET_RO_PROP2, SET_RO_PROP, SET_PROP_FUNC, SET_METHOD
По этим макросам я написал комментарии в internal.h.

По поводу properties: read-only property я реализовал как функцию которую можно установить макросом SET_PROP_FUNC. Но честно говоря мне не очень нравится этот подход. Такую функцию нельзя использовать как setter, а только как getter. Можно подправить парсер и при присваивании проверять, не присваивается ли значение атрибуту которое на самом деле такая property function, и если да, вызвать функцию с аргументами. Но можно придумать и какой-то другой вариант. Например, в каждом объекте тупо добавлять такие атрибуты - но потом за ними придется следить (например строка меняется - нужно изменить атрибут length и тп).

Про флаги: да, мне кажется битовые поля удобнее флагов.
Только зачем их заворачивать в union? Не проще просто

    struct v7_val {
       ...
       unsigned foo:1; 
       unsigned bar:1; 
    }

typeof error

v7.exe -e "print('typeof result = ' + typeof 'dfgdfg');"
Error executing [print('typeof result = ' + typeof 'dfgdfg');]: line 1: type error

Похоже, это связано с использованием ключевых слов внутри строковых литералов.

Debugging interface

Hi Sergey,

I believe the debugging interface is something that definitely need to be provided as an API for V7 engine. It is handy, because users might want to debug their scripts using favorite IDEs (e.g. Visual Studio). So there is should be a way to see the callstack, variables, threads, etc.

Sorry, if I put this not into appropriate place...

Build on Arduino

Complete V7 build on one of the smaller Arduino boards.
Publish build file.

/x*/ regexp should match an empty substring

With node:

console.log("should match empty string at index 0".match(/x*/))
[ '', index: 0, input: 'should match empty string at index 0' ]

With v7:

print("should match empty string at index 0".match(/x*/))

yields

null

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.