Code Monkey home page Code Monkey logo

nidium / nidium Goto Github PK

View Code? Open in Web Editor NEW
1.1K 53.0 65.0 11.79 MB

nidium is an ongoing effort for a mobile hw-accelerated rendering engine to create apps and games. Embedding Mozilla JavaScript VM, Google Skia, Facebook Yoga. https://twitter.com/nidiumproject for updates

Home Page: https://www.nidium.com

License: Other

Python 4.21% C 0.94% Shell 1.80% R 0.82% C++ 62.60% Objective-C 0.19% Objective-C++ 1.63% JavaScript 22.30% CMake 0.18% Java 4.25% nesC 1.01% AppleScript 0.08%
spidermonkey rendering layout-engine javascript c-plus-plus linux macos mozilla skia 2d-canvas

nidium's Introduction


nidium

Introduction

nidium is an ongoing effort for a general purpose rendering engine to create apps and games that run on both desktop and mobile. It also offers a way to create server-side applications through nidium-server which shares all the non graphics related code base.

nidium helps you create graphical software with Javascript. It's not a NodeJS, QT, Chromium, or WebKit derivative. It has been designed from scratch and has a small codebase written in C++.

It leverages the combination of Skia Graphics from Google, and Mozilla's JavaScript Engine (SpiderMonkey) together with many more awesome libraries.

It supports various common and well known APIs such as:

  • WebGL
  • Canvas 2D Context
  • WebSocket (client & server)
  • Module loading (require())

And some other non standard:

  • UDP/TCP Socket (client & server)
  • HTTP (client & server)
  • File access
  • Threading
  • Threaded Audio
  • Videos
  • Fragment shader on 2D canvas
  • Local Key/Value database

It can seamlessly run various JavaScript libraries like Three.JS, PixiJS, Phaser (and probably a lot more without much modification).

What problem(s) is nidium trying to solve

To put it simply, nidium aims to expose something close to web technology but in an easily hackable environment.

We're not trying to copy the Web. Think of it as a sandbox where you can quickly prototype new things, without any dependency to blink/webkit (e.g. like Electron does). This allows us to add various optimizations and non standard things. Moreover, nidium is small (nidium statically linked with all of its dependencies is about 20 MB).

Also, nidium aims to target a large spectrum of devices and our short term goal is to run it on low-power devices (mobile, rpi, ...)

By the way, it uses SpiderMonkey as its JavaScript engine, and we believe that Mozilla needs some love too!

Work in progress

nidium is still a work in progress and several key features are missing:

  • App distribution (create actual app out of nidium)
  • Microsoft Windows support
  • Good documentation

Layout engine

nidium ships with its own layout engine. That is, every element has its own memory buffer (retained mode), pretty similar to HTML elements.

The layout engine allows several "layout" operations to be made on each element (relative position, opacity, drag'n'drop, margin, scrolling, overflow, and so on).

It also implements a simple HTML DOM compatility layer and is mature enough to run a MVVM framework like Vue.js and probably React with little to no effort.

Network and event loop

nidium uses its own high-performance library (libapenetwork) which handles all the networking operations in a non-blocking, async way.

Download nidium

You can download nidium binaries for Linux and OSX from the download page.

Building nidium

To build nidium you need at least 5.7GB of disk space. A build from scratch may take 30 to 90 minutes, depending of the speed of your computer.

On a debian based system, a few commands will get you started.

$ apt-get install libpci-dev python2.7 git make patch clang pkg-config libgtk2.0-dev libgtk-3-dev mesa-common-dev libglu1-mesa-dev libosmesa6-dev yasm libasound2 libasound2-dev libbz2-1.0
$ git clone https://github.com/nidium/NidiumTools.git
$ git clone --recursive https://github.com/nidium/Nidium.git
$ export PYTHONPATH=$(pwd)/NidiumTools/src
$ cd Nidium
$ ./configure_frontend
$ ./bin/nidium

On a mac-os based system you need xcode installed.

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
$ git clone https://github.com/nidium/NidiumTools.git
$ git clone --recursive https://github.com/nidium/Nidium.git
$ export PYTHONPATH=$(pwd)/NidiumTools/src
$ cd Nidium
$ ./configure_frontend
$ ./bin/nidium

Documentation

We strive to have excellent documentation, both for our getting started guide and for the API Reference.

Videos - nidium in action

Bug reports and Collaboration

Feel free to report any bug or issue to us.

If you feel that something is not clear, that could be an issue worth reporting and solving.

License

Copyright 2017 Nidium Inc. All rights reserved. Use of this source code is governed by a MIT license that can be found in the LICENSE file.

nidium's People

Contributors

cookiengineer avatar efyx avatar fredericandre avatar murrayluke avatar paraboul avatar verpeteren 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

nidium's Issues

Canvas paint event

Currently, JS Canvas object has a "load" and "resize" event.

The "paint" event is missing (call for redraw).

OpenGL context version

SDL doesn't seem to chose the best version available.

We need to figure out what's the lowest and highest version we want (only core profile?).
Does skia accepts core profile only?

GTK / File Dialogs

Is there an API available to open a GTK File dialog to open files from the system's native file browser?

That would ease up interaction with files much more. Otherwise, I guess, somebody would have to implement their own filesystem dialog in canvas / webgl to navigate around the system.

So if it's not available, this would be a feature request for:

  • Open File Dialog
  • Save File Dialog

logging atomicity

Since the introduction of async logging, it's possible for a log() call to trigger pending messages.
console.log() does multiple call to log() (e.g. for line feed), breaking its message atomicity.

We should create a temp buffer before posting the log message.

A good idea would be to add something lke ->logBufferStart() and ->logFlush()

WebSocket can't write in onopen()

    var server = new WebSocketServer("ws://127.0.0.1:9099/");

    server.onopen = function(client) {
        client.send("foo"); // does not work
    }

    server.onmessage = function(client, ev) {

    }

    server.onclose = function(client) {

    }

If the send() operation is delayed (e.g. setTimeout()), it works as expected.

It's also worth trying using regular Socket().

Installing nidium on linux as super user does not work

I want to try Nidium and installed on my system but after the install when I try to execute /usr/local/bin/nidium I get the error is a directory.
The file manager see that as a directory but when I open it I got an error too.

What problem(s) is nidium trying to solve

Hi there!
Seems like you put a lot of effort into this and there is also API documentation and stuff.

I had a quick look over the README and the Getting-started, but I am still puzzled regarding the very basics:

What problem(s) is Nidium trying to solve
and what is the benefit of using Nidium instead of existing Node eco system

That is the very first thing I am usually interested in. Maybe you can explain it better :)

Cheers

Nidium [android-branch] crashes when the phone is in airplane mode and a second attempt is started

Steps to reproduce:

  1. Set phone in airplane mode
  2. Load the Nidroid app
  3. Click the 'load' button to load the default '.nml' via internet
  4. Wait some seconds (+-13)
  5. Again; Click the 'load' button, to load the default '.nml' via internet
  6. Again; Wait some seconds (+-13)
  7. crash.

step 1 + 2, can be change; the result is the same.

02-15 09:04:23.234 8468-8468/com.nidium.android D/ViewRootImpl: ViewPostImeInputStage processPointer 0
02-15 09:04:23.374 8468-8468/com.nidium.android D/ViewRootImpl: ViewPostImeInputStage processPointer 1
02-15 09:04:23.374 8468-8468/com.nidium.android D/NidiumLauncher: Loading file http://p.nf/android.nml
02-15 09:04:23.374 8468-8468/com.nidium.android I/Timeline: Timeline: Activity_launch_request id:com.nidium.android time:177543399
02-15 09:04:23.404 8468-8468/com.nidium.android D/AbsListView: Get MotionRecognitionManager
02-15 09:04:23.414 8468-8468/com.nidium.android D/AbsListView:  onsize change 
02-15 09:04:23.484 8468-8468/com.nidium.android V/SDL: Device: a3ulte
02-15 09:04:23.484 8468-8468/com.nidium.android V/SDL: Model: SM-A300FU
02-15 09:04:23.484 8468-8468/com.nidium.android V/SDL: onCreate(): null
02-15 09:04:23.504 8468-8468/com.nidium.android V/SDL: onResume()
02-15 09:04:23.504 8468-8468/com.nidium.android D/SecWifiDisplayUtil: Metadata value : none
02-15 09:04:23.504 8468-8468/com.nidium.android D/ViewRootImpl: #1 mView = com.android.internal.policy.PhoneWindow$DecorView{eebd688 I.E...... R.....ID 0,0-0,0}
02-15 09:04:23.534 8468-8468/com.nidium.android V/SDL: surfaceCreated()
02-15 09:04:23.534 8468-8468/com.nidium.android V/SDL: surfaceChanged()
02-15 09:04:23.534 8468-8468/com.nidium.android V/SDL: pixel format RGB_565
02-15 09:04:23.544 8468-8468/com.nidium.android V/SDL: Window size: 540x924
02-15 09:04:23.544 8468-8468/com.nidium.android D/SensorManager: registerListener :: 0, BMC150 Acceleration Sensor, 20000, 0,  
02-15 09:04:23.564 8468-8682/com.nidium.android I/SDL: SDL_Android_Init()
02-15 09:04:23.564 8468-8682/com.nidium.android I/SDL: SDL_Android_Init() finished!
02-15 09:04:23.564 8468-8468/com.nidium.android D/ViewRootImpl: MSG_RESIZED_REPORT: ci=Rect(0, 36 - 0, 0) vi=Rect(0, 36 - 0, 0) or=1
02-15 09:04:23.564 8468-8468/com.nidium.android V/SDL: onWindowFocusChanged(): true
02-15 09:04:23.564 8468-8682/com.nidium.android D/../../../src/Interface/android/AndroidMain.cpp:: argc=2
02-15 09:04:23.564 8468-8682/com.nidium.android D/../../../src/Interface/android/AndroidMain.cpp:: app_process
02-15 09:04:23.564 8468-8682/com.nidium.android D/../../../src/Interface/android/AndroidMain.cpp:: http://p.nf/android.nml
02-15 09:04:23.564 8468-8682/com.nidium.android D/../../../src/Interface/android/AndroidMain.cpp:: Loading argument http://p.nf/android.nml
02-15 09:04:23.604 8468-8468/com.nidium.android I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@5ba222b time:177543625
02-15 09:04:23.834 8468-8468/com.nidium.android V/ActivityThread: updateVisibility : ActivityRecord{5b6b607 token=android.os.BinderProxy@17261e0 {com.nidium.android/com.nidium.android.MainActivity}} show : false
02-15 09:04:38.654 8468-8682/com.nidium.android A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x690073 in tid 8682 (SDLThread)
02-15 09:04:39.774 9163-9163/com.nidium.android D/AbsListView: Get MotionRecognitionManager
02-15 09:04:39.794 9163-9163/com.nidium.android E/MotionRecognitionManager: mSContextService = null
02-15 09:04:39.794 9163-9163/com.nidium.android E/MotionRecognitionManager: motionService = com.samsung.android.motion.IMotionRecognitionService$Stub$Proxy@39df012
02-15 09:04:39.834 9163-9163/com.nidium.android D/SecWifiDisplayUtil: Metadata value : none
02-15 09:04:39.834 9163-9163/com.nidium.android D/ViewRootImpl: #1 mView = com.android.internal.policy.PhoneWindow$DecorView{ac61c99 I.E...... R.....ID 0,0-0,0}
02-15 09:04:39.844 9163-9217/com.nidium.android D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
02-15 09:04:39.894 9163-9217/com.nidium.android I/Adreno-EGL: <qeglDrvAPI_eglInitialize:379>: EGL 1.4 QUALCOMM build: Nondeterministic_AU_msm8916_32_LA.BR.1.2.6_RB1__release_AU (Ia10634f51b)
                                                              OpenGL ES Shader Compiler Version: XE031.06.00.05
                                                              Build Date: 01/04/16 Mon
                                                              Local Branch: 
                                                              Remote Branch: quic/LA.BR.1.2.6_rb1.7
                                                              Local Patches: NONE
                                                              Reconstruct Branch: NOTHING
02-15 09:04:39.904 9163-9217/com.nidium.android I/OpenGLRenderer: Initialized EGL, version 1.4
02-15 09:04:39.964 9163-9163/com.nidium.android D/AbsListView:  onsize change 
02-15 09:04:39.974 9163-9217/com.nidium.android D/libGLESv1: DTS_GLAPI : DTS is not allowed for Package : com.nidium.android
02-15 09:04:39.984 9163-9163/com.nidium.android D/ViewRootImpl: MSG_RESIZED_REPORT: ci=Rect(0, 36 - 0, 0) vi=Rect(0, 36 - 0, 0) or=1
02-15 09:04:40.014 9163-9163/com.nidium.android I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@17261e0 time:177560032

BTW, it seems that there is no error when the phone has no wifi connection.

link error: jpeg library missing after skia update

[DEBUG ] Running gyp. File=/data/Development/nidium/Nidium/gyp/all.gyp Target=None
[INFO  ] Executing make -j12
  LINK(target) ../bin/nidium
/usr/bin/ld: error: cannot find -ljpeg

With older versions of skia this was located in /third-party/.default/skia/out/Release/obj/gyp/libjpeg.a
It appears that libturbo is used now third-party/.default/skia/third_party/externals/libjpeg-turbo/release/libturbojpeg.pc.in

Assets atomic issue

    <assets>
        <script src="test.js"></script>
    </assets>

    <assets>
        <script src="test.js"></script>
    </assets>

It's possible that the first JS file trigger a postMessage() and run the second JS file when executing (Doing a kind of preemptive execution).

We should avoid that and wait for the first script to finish.

Window resize events, viewport size and fullscreen mode

Is there something like a window.onresize = function(){} available on the global object?

When looking at the bindings, I found something like sizeChanged(width, height) that seems to be called, but I couldn't find it somewhere else.

Other ways of resizing the window (setting innerWidth, innerHeight or calling setSize()) seem to fire no event or callback.

My questions are now as follows:

  • Is there a way to get the viewport size (like 1920x1080 when my window is smaller)?
  • If not, is there a way to get resize events of the window when the user maximizes it?
  • Fullscreen mode could be optional, if not wanted - but if so, dependencies would be the previous two points to implement it manually.

Use case could be as follows:

window.addEventListener('resize', function(width, height) {
    console.log('window was resized by user, need to resize my canvas nao');
});


let mybutton = new DummyFullscreenButton();

mybutton.bind('touch', function() {
    if (window.viewportWidth < window.innerWidth || window.viewportHeight < window.innerHeight) {
        window.setSize(window.viewportWidth, window.viewportHeight);
    }
});

Nidium-server: AddressSanitizer CHECK failed

When trying to use the provided Nidium server binary, it currently fails on ArchLinux. When googling that error up, there was an already fixed issue related to llvm and clang, but that seems to be fixed for other projects as of now. Upstream libraries already contain the fix in their latest versions: https://bugs.archlinux.org/task/50366

 ./nidium-server 
==4511==AddressSanitizer CHECK failed: /tmp/buildd/llvm-toolchain-3.5-3.5/projects/compiler-rt/lib/asan/asan_rtl.cc:558 "((!asan_init_is_running && "ASan init calls itself!")) != (0)" (0x0, 0x0)
    <empty stack>

Software versions:

  • ArchLinux (HEAD / up to date)
  • llvm-libs 3.9.1-2
  • gcc-libs 6.3.1-2

So, in order to find out what the problem is, I probably need to recompile Nidium-server on my machine. I would guess that the buildbot is a legacy Debian/Ubuntu installation, as many projects have similar troubles with an LTS version that still hasn't merged the upstream fixes for the sanitizer.

I will report back when nidium is recompiled on my machine and tested, so that I can verifiy this is related to your buildbot ^_^

JSEvents issues

We should rework the JSEvents class :

  • It should be exposed to the userland through ClassMapper as EventEmitter base class (NodeJS compat).
  • ClassMapperWithEvents<T> that currently implements JSEvents should somehow inherit the prototype.
  • JSEvents::CreateEventObject() should also uses a prototyped object rather than implementing JSEvents_funcs everytime.

png

Move document.canvas from C++ to JS

We should create document.canvas in JS (probably in the _onready handler).
This would allow us to use a NidiumNode rather than a raw Canvas instance.

Also, document.documentElement should alias document.canvas

nidium-server has compile warning for linenoise.

While building 'nidium-server' the compiler raises several warnings.
Is this because we are using an old version of linenoise or are our modifications causing this?

CC(target) out/Release/obj.target/nidium-server/third-party/linenoise/linenoise.o
../third-party/linenoise/linenoise.c:775:38: warning: if statement has empty body [-Wempty-body]
    if (pipe(linenoise_pipefds) < 0) ;
                                     ^
../third-party/linenoise/linenoise.c:775:38: note: put the semicolon on a separate line to silence this warning
../third-party/linenoise/linenoise.c:785:48: warning: if statement has empty body [-Wempty-body]
        if (write(1, "\x1b[0G\x1b[0K", 8) < 0) ;
                                               ^
../third-party/linenoise/linenoise.c:785:48: note: put the semicolon on a separate line to silence this warning
../third-party/linenoise/linenoise.c:797:53: warning: if statement has empty body [-Wempty-body]
        if (write(linenoise_pipefds[1], &x, 1) < 0) ;
                                                    ^
../third-party/linenoise/linenoise.c:797:53: note: put the semicolon on a separate line to silence this warning
../third-party/linenoise/linenoise.c:840:56: warning: if statement has empty body [-Wempty-body]
            if (read(linenoise_pipefds[0], &x, 1) < 0) ;
                                                       ^
../third-party/linenoise/linenoise.c:840:56: note: put the semicolon on a separate line to silence this warning
4 warnings generated.

windows support

I urgently need a microsoft windows binary of Nidium.

Is there a chance to get it in near future ?

ClassMapper : root() and different JS Context

While porting the A/V part of Nidium to ClassMapper I have noticed an issue with CreateUniqueInstance() and more generally speaking about the root() method.

In the JSContext of the audio thread I'am calling JSConsole::RegisterObject(threadJSContext); this is resulting in the following crash :

    #0 0x9a5694 in Nidium::Binding::NidiumJS::rootObjectUntilShutdown(JSObject*) /home/efyx/dev/nidium/Nidium.verpeteren/build/../src/Binding/NidiumJS.cpp:114:28
    #1 0xa053a6 in Nidium::Binding::ClassMapper<Nidium::Binding::JSConsole>::root() /home/efyx/dev/nidium/Nidium.verpeteren/build/../src/Binding/ClassMapper.h:314:9
    #2 0xa053a6 in Nidium::Binding::ClassMapper<Nidium::Binding::JSConsole>::setUniqueInstance() /home/efyx/dev/nidium/Nidium.verpeteren/build/../src/Binding/ClassMapper.h:198
    #3 0xa053a6 in Nidium::Binding::ClassMapper<Nidium::Binding::JSConsole>::CreateUniqueInstance(JSContext*, Nidium::Binding::JSConsole*, char const*) /home/efyx/dev/nidium/Nidium.verpeteren/build/../src/Binding/ClassMapper.h:219
    #4 0xa04f39 in Nidium::Binding::JSConsole::RegisterObject(JSContext*) /home/efyx/dev/nidium/Nidium.verpeteren/build/../src/Binding/JSConsole.cpp:141:5
    #5 0x8e613b in Nidium::Binding::JSAudioContext::createContext() /home/efyx/dev/nidium/Nidium.verpeteren/build/../src/Binding/JSAudioContext.cpp:413:5

We probably want a generic way to initialize a new JSContext and set the GC root tracer on the newly created context so the integration with the class mapper can be seamless.

regression of performance: fps on the 'stars.nml' demo

Around 2016/01/27 a demo application 'stars.nml' ran at about 60 fps.
Currently (2017/12/37) it seems to run at about 30fps.

A prelimanary investigation indicates that the loss of performance happens somewere before 2016/06/20.

<application framework="false" version="0.1">
<!--
/* -------------------------------------------------------------------------- */
/* MIT license                                          (c) 2016 Nidium, Inc. */
/* -------------------------------------------------------------------------- */
/* Permission is hereby granted, free of charge, to any person obtaining a    */
/* copy of this software and associated documentation files (the "Software"), */
/* to deal in the Software without restriction, including without limitation  */
/* the rights to use, copy, modify, merge, publish, distribute, sublicense,   */
/* and/or sell copies of the Software, and to permit persons to whom the      */
/* Software is furnished to do so, subject to the following conditions:       */
/*                                                                            */
/* The above copyright notice and this permission notice shall be included in */
/* all copies or substantial portions of the Software.                        */
/*                                                                            */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   */
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    */
/* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING    */
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER        */
/* DEALINGS IN THE SOFTWARE.                                                  */
/* -------------------------------------------------------------------------- */
-->
    <meta>
        <title>Test case</title>
        <viewport> 800x600</viewport>
        <version>1.0</version>
        <date>2012-03-15</date>
        <robots>index, follow</robots>
        <identifier>com.nidium.app.demos.stars</identifier>
        <author>Nidium Inc.</author>
    </meta>
    <assets>
        <script>
            var canvas = document.canvas;
            var ctx = canvas.getContext("2d");
            document.showFPS(true);

            var particule = function(ctx) {
                this.ctx = ctx;
                this.reset();

                this.sizes = {
                    halfWidth: canvas.width / 2,
                    halfHeight: canvas.height / 2
                }
            }

            particule.prototype.reset = function() {
                this.positions = {
                    x: 2 * (Math.random() - 0.5),
                    y: 2 * (Math.random() - 0.5),
                    z: 1
                }
            }

            particule.prototype.draw = function() {
                //this.ctx.save();
                this.ctx.fillStyle = "#FFF";

                this.positions.z -= 0.01;

                var x = (this.positions.x / this.positions.z) * this.sizes.halfWidth + this.sizes.halfWidth;
                var y = (this.positions.y / this.positions.z) * this.sizes.halfHeight + this.sizes.halfHeight;

                if (x <= 0 || x > canvas.width || y <= 0 || y > canvas.height) {
                    this.reset();
                }

                this.ctx.fillRect(x, y, 1, 1);

                //this.ctx.restore();
            }


            var stars = [];

            for (var i = 0; i < 4096*4; i++) {
                stars[i] = new particule(ctx);
            }


            function draw()
            {
                ctx.fillStyle = "#000";
                ctx.fillRect(0, 0, canvas.width, canvas.height);

                for (var i = 0; i < stars.length; i++) {
                    stars[i].draw();
                }

                window.requestAnimationFrame(draw);
            }

            draw();

            /*ctx.fillStyle = "blue";
            //ctx.fillRect(0, 0, 20, 20);
            console.log("default", ctx.fillStyle);

            var img = new Image();
            img.src = "./pattern.png";
            img.onload = function() {
                var pattern = ctx.createPattern(img, "repeat");
                ctx.fillStyle = pattern;

                console.log("Pattern set");
                console.log("New fillstyle", ctx.fillStyle);

                ctx.save();

                console.log("After save", ctx.fillStyle);
                ctx.fillRect(0, 0, 800, 800);

                ctx.fillStyle = "red";

                console.log("remove pattern", ctx.fillStyle);

                ctx.restore();

                ctx.fillStyle = "yellow";
                console.log("After restore", ctx.fillStyle);
            }*/

        </script>
    </assets>
</application>



Install on ubuntu 16.04 breaks desktop environment

I installed the 64 bit version of Nidium on ubuntu, ran it with example hello world app and whole system came to a halt and screen flickered then went blank. Did a reboot and my desktop environment is gone.

Looking at the install logs i had an issue with libEGL not being a symlink. Have no other information as because i have to do a reinstall to get access back.

Networking: How to transfer binary data?

I just started to use Nidium and I guess I need help to understand what APIs are available.

Is there a way to transfer binary data over the wire? How is this solved, is there something like a Buffer API similar to node.js or how do you realize the encoding/decoding of binary data into utf8 strings and uint8 integers so that you effectively can modify binary data in the JS context?

New logging system

Currently nidium/libapenetwork use a lot of printf() for printing debugging information. We need to clean this with a unified API.

Goals

  • Handle different logging level (debug, error, verbose, info) that should be configurable at build time
  • Logging backend should be overwritable (so we can either use a bare printf() or nidium logging system)
  • Each logged message should have a tag associated, so when debugging we can filter out what we want to see (buildtime and/or runtime)
  • Use C code (so it can be used in libapenetwork) and has a C++ wrapper for convenience

Implementation details

  • Use macros or functions ?
  • As an external library or header only file ?

API proposal

  • Proposal 1 :
logSetLogger(loggingWrapperFunction)
log("LogTag", kLog_Error, "Print a string %s", str);
// OR
logError("LogTag", "Print a string %s", str);
  • Proposal 2 :
Logger::Set(loggingWrapperFunction);
Logger log("LogTag"); 
log.error("This is an error message");

Embeded module lookup

require() doesn't work on embed:// path. Shouldn't require() works with any stream allowing AllowLocalFileStream?

Also, Embed directory / builtin, should be added to the lookup chain for modules, so that we can easily create "native" js module.

I was thinking to something like :

src/Embed/ => regular embedded JS files (or resources) (not modules).
src/Embed/lib/ => public builtin JS modules

e.g. require("foo"); would look up to src/Embed/lib/foo.js (or whichever virtualization embed:// is bound to).

Application Packaging

In order to create a packaging tool for nidium that would bundle nidium and an application in a single file, some stuff needs to be done :

  • Binding/JSModules.cpp have call to stat(), access(), realpath()
  • Core/Path.cpp have a call to realpath()
  • Packaging format needs to be (re)defined and src/Frontend/App.cpp needs to be updated
  • We need a tool (using the dir2nvfs utility) to package resources into a single file
  • Pack BLOB file in a modified nidium binary (without a compiler). Various possibility : Add the end of the file (Does this break ELF?).
  • Application icon can be supplied by the user
  • src/Binding/JSNFS.cpp needs to be merged inside src/Tools/dir2nvfs.cpp

'new HTTP' segfault

This happens on the classmapper branch

nidium> new HTTP("http://www.nidium.com/", function(ev) {
... console.log(ev.data);
... });

Program received signal SIGSEGV, Segmentation fault.
js::ObjectImpl::setSlot (this=0x0, slot=0, value=...)
    at /data/Development/nidium/Nidium/third-party/.default/mozilla-central/js/src/vm/ObjectImpl.h:728
728         getSlotRef(slot).set(this->asObjectPtr(), HeapSlot::Slot, slot, value);
(gdb) bt
#0  js::ObjectImpl::setSlot (this=0x0, slot=0, value=...)
    at /data/Development/nidium/Nidium/third-party/.default/mozilla-central/js/src/vm/ObjectImpl.h:728
#1  0x00000000006a738e in setReservedSlot (this=0x0, index=0, v=...)
    at /data/Development/nidium/Nidium/third-party/.default/mozilla-central/js/src/jsobj.h:428
#2  JS_SetReservedSlot (obj=0x0, index=0, value=...)
    at /data/Development/nidium/Nidium/third-party/.default/mozilla-central/js/src/jsapi.cpp:3761
#3  0x000000000051850d in Nidium::Binding::JSHTTP::request (this=0x198ee60, cx=0x195a500, options=..., callback=...)
    at ../src/Binding/JSHTTP.cpp:184
#4  0x000000000051791a in Nidium::Binding::JSHTTP::Constructor (cx=0x195a500, args=..., obj=...) at ../src/Binding/JSHTTP.cpp:98
#5  0x000000000051aacc in Nidium::Binding::ClassMapper<Nidium::Binding::JSHTTP>::JSConstructor<0> (cx=0x195a500, 
    argc=<optimized out>, vp=<optimized out>) at ../src/Binding/ClassMapper.h:449
#6  0x00000000007b30cb in CallJSNative (
    native=0x51aa60 <Nidium::Binding::ClassMapper<Nidium::Binding::JSHTTP>::JSConstructor<0>(JSContext*, unsigned int, JS::Value*)>, 
    cx=<optimized out>, args=...) at /data/Development/nidium/Nidium/third-party/.default/mozilla-central/js/src/jscntxtinlines.h:239
#7  CallJSNativeConstructor (
    native=0x51aa60 <Nidium::Binding::ClassMapper<Nidium::Binding::JSHTTP>::JSConstructor<0>(JSContext*, unsigned int, JS::Value*)>, 
    cx=<optimized out>, args=...) at /data/Development/nidium/Nidium/third-party/.default/mozilla-central/js/src/jscntxtinlines.h:272
#8  js::InvokeConstructor (cx=0x195a500, args=...)
    at /data/Development/nidium/Nidium/third-party/.default/mozilla-central/js/src/vm/Interpreter.cpp:553
#9  0x00000000007ae470 in Interpret (cx=0x195a500, state=...)
    at /data/Development/nidium/Nidium/third-party/.default/mozilla-central/js/src/vm/Interpreter.cpp:2617
#10 0x00000000007a5db6 in js::RunScript (cx=0x195a500, state=...)
    at /data/Development/nidium/Nidium/third-party/.default/mozilla-central/js/src/vm/Interpreter.cpp:422
#11 0x00000000007b3677 in js::ExecuteKernel (cx=0x195a500, script=..., scopeChainArg=..., thisv=..., type=js::EXECUTE_GLOBAL, 
    evalInFrame=..., result=<optimized out>)
    at /data/Development/nidium/Nidium/third-party/.default/mozilla-central/js/src/vm/Interpreter.cpp:630
#12 0x00000000007b37a8 in js::Execute (cx=0x195a500, script=..., scopeChainArg=..., rval=0x7fffffffe058)
    at /data/Development/nidium/Nidium/third-party/.default/mozilla-central/js/src/vm/Interpreter.cpp:666
#13 0x00000000006a9eca in ExecuteScript (cx=0x195a500, obj=..., scriptArg=..., rval=0xfffb000000000000)
    at /data/Development/nidium/Nidium/third-party/.default/mozilla-central/js/src/jsapi.cpp:4797
#14 0x0000000000510aee in Nidium::Binding::NidiumJS::LoadScriptContentAndGetResult (this=0x1924d20, data=<optimized out>, 
    len=<optimized out>, filename=<optimized out>) at ../src/Binding/NidiumJS.cpp:829
#15 0x000000000050c680 in Nidium::Server::REPL::onMessage (this=0x19863f0, msg=...) at ../src/Server/REPL.cpp:100
#16 0x00000000005317d9 in Nidium::Core::Messages_handle (arg=<optimized out>) at ../src/Core/Messages.cpp:35
#17 0x000000000055fdee in ape_timers_process (ape_ctx=0x18eeb50) at ../src/libapenetwork/src/ape_timers_next.c:152
#18 0x000000000055dc12 in APE_loop_run (ape=0x18eeb50) at ../src/libapenetwork/src/ape_events_loop.c:144
#19 0x000000000050bc5d in Nidium::Server::Worker::run (this=<optimized out>, argc=<optimized out>, argv=<optimized out>, 
0 0x000000000050bee2 in initWorker (this=0x18ed9f0, idx=<optimized out>) at ../src/Server/Server.cpp:155
#21 Nidium::Server::Server::init (this=0x18ed9f0) at ../src/Server/Server.cpp:285
#22 0x00007ffff6c07b45 in __libc_start_main (main=0x50b7c0 <main(int, char**)>, argc=1, argv=0x7fffffffe3e8, init=<optimized out>, 
    fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe3d8) at libc-start.c:287
#23 0x000000000050b6de in _start ()

Building issues

We should get rid of builing issues for good.

Here are the issues I encountered when building from scratch on macOS (./configure_frontend --assume-yes) :

  • Question asked If I wanted to remove an inexistant directory.
  • --assume-yes is required otherwise lot of question are asked.
  • Python error : see nidium/NidiumTools#3
  • re run ./configure_frontend tries to rebuild everything the second time (but not the third time) (I removed the --assume-yes)
  • yasm not found (should we download a binary on the fly?)

Wayland support

Not sure if Wayland desktop supports X11 API?

SDL, for instance, has separate video driver for wayland since 2.0.2.

@efyx thought ?, @verpeteren can you build and run nidium on a wayland enabled linux desktop to check if our X11 interface work there?

Canvas : staticRight + fluidHeight not working as expected

For drawing a canvas that takes the full width of it's parent and adjust his height to it's content I am using

canvas.staticRight = true; 
canvas.right = 0; 
canvas.fluidHeight = true;

However the result is not the expected one. The parent canvas does not draw itself on the full width of it's parent.

Sample code :

<application version="0.1">
    <meta>
        <title>Demo</title>
        <viewport>800x600</viewport>
    </meta>
    <assets>
        <script>
var c = new Canvas(10, 10);
c.fluidHeight = true;
c.left = 0;
c.staticRight = true;
c.right = 0;

var c2 = new Canvas(50, 50);
var ctx = c2.getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(0, 0, 200, 200);
c2.opacity = 0.5;

c.add(c2);

document.canvas.add(c);

c.addEventListener("load", draw);
c.addEventListener("resize", draw);

function draw() {
    var ctx = c.getContext("2d");
    ctx.fillStyle = "blue";
    ctx.fillRect(0, 0, 800, 600);
    console.log("Canvas size", c.width, c.height);
}
        </script>
    </assets>
    <layout id="mainlayout">
    </layout>
</application>

Result :
image

Expected result :
image

Please note that :

  • The size reported by c.width/c.height are the expected one (800x50)
  • If c size is set to 10x50 and c2 size is set to 50x50, the end result is correct. (When the parent canvas height match the child height, it works as expected). Setting any other value will not work.
  • Disabling fluidHeight will make the canvas work as expected

ClassMapper : Remaining JSClass to be moved to ClassMapper

The following JSClass are still present as "raw" JSClass

JSWindow.cpp :

  • MouseEvent : Move to ClassMapper
  • DragEvent : Move to ClassMapper
  • TextInputEvent : Move to ClassMapper
  • keyEvent : Will be renamed KeyEvent
  • NMLEvent : Remove in favor of NidiumEvent
  • Navigator : Not moving to ClassMapper, will be moved to HTML5 shim, some features will be removed

JSThread.cpp

  • ThreadMessageEvent : Replace with NidiumEvent

JSEvents.cpp

- [ ] NidiumEvent : Move to ClassMapper
- [ ] NidiumErrorEvent : Move to ClassMapper

Important note : We should have some inheritance mechanism so all Event class can extend NidiumEvent / NidiumErrorEvent and thus implement some features like stopPropagation / preventDefault/etc...

still having an issue on OSX

After the last fix on OSX, I am still having an error after running ./configure_frontend

      std::__1::__tree<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::destroy(std::__1::__tree_node<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, void*>*) in libicutu.a(udbgutil.o)
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >::put(char)", referenced from:
      KnownIssues::print() in libicutu.a(udbgutil.o)
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >::flush()", referenced from:
      KnownIssues::print() in libicutu.a(udbgutil.o)
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >::sentry::sentry(std::__1::basic_ostream<char, std::__1::char_traits<char> >&)", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libicutu.a(udbgutil.o)
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >::sentry::~sentry()", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libicutu.a(udbgutil.o)
  "std::__1::cout", referenced from:
      KnownIssues::print() in libicutu.a(udbgutil.o)
  "std::__1::ctype<char>::id", referenced from:
      KnownIssues::print() in libicutu.a(udbgutil.o)
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libicutu.a(udbgutil.o)
  "std::__1::locale::~locale()", referenced from:
      KnownIssues::print() in libicutu.a(udbgutil.o)
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libicutu.a(udbgutil.o)
  "std::__1::ios_base::clear(unsigned int)", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in libicutu.a(udbgutil.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[6]: *** [icuinfo] Error 1
make[5]: *** [all-recursive] Error 2
make[4]: *** [all-recursive] Error 2
make[3]: *** [buildicu] Error 2
make[2]: *** [intl/icu/compile] Error 2
make[1]: *** [compile] Error 2
make: *** [default] Error 2
Failed to run previous command

Moreover, it would be more comfortable to have the option to force the download of all external dependencies than having to answer [Y/n] for each dependency.

error: templates must have C++ linkage and more..

Bellow what I have..

clang++ -o Compression.o -c  -I/nidium/Nidium/third-party/.default/mozilla-central/js/src/obj/dist/system_wrappers -include /nidium/Nidium/third-party/.default/mozilla-central/config/gcc_hidden.h -DIMPL_MFBT -I/nidium/Nidium/third-party/.default/mozilla-central/mfbt -I.  -I../dist/include  -I/nidium/Nidium/third-party/.default/mozilla-central/nsprpub/dist/include/nspr/        -fPIC  -DMOZILLA_CLIENT -include ../js/src/js-confdefs.h -MD -MP -MF .deps/Compression.o.pp -Qunused-arguments  -Qunused-arguments -Wno-inline-new-delete -Wall -Wsign-compare -Wtype-limits -Wno-invalid-offsetof -Wno-c++0x-extensions -Wno-extended-offsetof -Wno-unknown-warning-option -Wno-return-type-c-linkage -fno-rtti -fno-exceptions -fno-math-errno -std=gnu++0x -pthread -pipe  -DNDEBUG -DTRIMMED -g -O3 -fomit-frame-pointer   -Wno-unused-function  /nidium/Nidium/third-party/.default/mozilla-central/mfbt/Compression.cpp
Note: rebuild with "make VERBOSE=1 " to show all compiler parameters.
Decimal.o
make[4]: Making `all' in `stubdata'
make[5]: Entering directory '/nidium/Nidium/third-party/.default/mozilla-central/js/src/obj/intl/icu/target/stubdata'
make[5]: Nothing to be done for 'all'.
make[5]: Leaving directory '/nidium/Nidium/third-party/.default/mozilla-central/js/src/obj/intl/icu/target/stubdata'
make[4]: Making `all' in `common'
In file included from /nidium/Nidium/third-party/.default/mozilla-central/mfbt/Compression.cpp:7:
In file included from ../dist/include/mozilla/Compression.h:12:
In file included from ../dist/include/mozilla/Assertions.h:43:
In file included from /nidium/Nidium/third-party/.default/mozilla-central/js/src/obj/dist/system_wrappers/stdlib.h:3:
In file included from /usr/include/stdlib.h:42:
In file included from /usr/include/x86_64-linux-gnu/bits/waitstatus.h:64:
In file included from /nidium/Nidium/third-party/.default/mozilla-central/js/src/obj/dist/system_wrappers/endian.h:3:
In file included from /nidium/Nidium/third-party/.default/mozilla-central/mfbt/endian.h:70:
../dist/include/mozilla/DebugOnly.h:36:1: error: templates must have C++ linkage
template<typename T>
^~~~~~~~~~~~~~~~~~~~
In file included from /nidium/Nidium/third-party/.default/mozilla-central/mfbt/Compression.cpp:7:
In file included from ../dist/include/mozilla/Compression.h:12:
In file included from ../dist/include/mozilla/Assertions.h:43:
In file included from /nidium/Nidium/third-party/.default/mozilla-central/js/src/obj/dist/system_wrappers/stdlib.h:3:
In file included from /usr/include/stdlib.h:42:
In file included from /usr/include/x86_64-linux-gnu/bits/waitstatus.h:64:
In file included from /nidium/Nidium/third-party/.default/mozilla-central/js/src/obj/dist/system_wrappers/endian.h:3:
In file included from /nidium/Nidium/third-party/.default/mozilla-central/mfbt/endian.h:71:
../dist/include/mozilla/TypeTraits.h:26:1: error: templates must have C++ linkage
template<typename> struct RemoveCV;
^~~~~~~~~~~~~~~~~~
../dist/include/mozilla/TypeTraits.h:27:1: error: templates must have C++ linkage
template<typename> struct AddRvalueReference;
^~~~~~~~~~~~~~~~~~
../dist/include/mozilla/TypeTraits.h:38:10: error: expected a qualified name after 'typename'
typename AddRvalueReference<T>::Type DeclVal();
         ^
../dist/include/mozilla/TypeTraits.h:37:1: error: templates must have C++ linkage
template<typename T>
^~~~~~~~~~~~~~~~~~~~
../dist/include/mozilla/TypeTraits.h:38:28: error: expected ';' at end of declaration
typename AddRvalueReference<T>::Type DeclVal();
                           ^
../dist/include/mozilla/TypeTraits.h:38:28: error: expected unqualified-id
../dist/include/mozilla/TypeTraits.h:46:1: error: templates must have C++ linkage
template<typename T, T Value>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../dist/include/mozilla/TypeTraits.h:55:9: error: unknown type name 'IntegralConstant'
typedef IntegralConstant<bool, true> TrueType;
        ^
../dist/include/mozilla/TypeTraits.h:55:25: error: expected unqualified-id
typedef IntegralConstant<bool, true> TrueType;
                        ^
../dist/include/mozilla/TypeTraits.h:56:9: error: unknown type name 'IntegralConstant'
typedef IntegralConstant<bool, false> FalseType;
        ^
../dist/include/mozilla/TypeTraits.h:56:25: error: expected unqualified-id
typedef IntegralConstant<bool, false> FalseType;
                        ^
../dist/include/mozilla/TypeTraits.h:64:1: error: templates must have C++ linkage
template<typename T>
^~~~~~~~~~~~~~~~~~~~
../dist/include/mozilla/TypeTraits.h:65:23: error: expected class name
struct IsVoidHelper : FalseType {};
                      ^
../dist/include/mozilla/TypeTraits.h:68:8: error: explicit specialization of non-template struct 'IsVoidHelper'
struct IsVoidHelper<void> : TrueType {};
       ^           ~~~~~~
../dist/include/mozilla/TypeTraits.h:68:29: error: expected class name
struct IsVoidHelper<void> : TrueType {};
                            ^
../dist/include/mozilla/TypeTraits.h:80:1: error: templates must have C++ linkage
template<typename T>
^~~~~~~~~~~~~~~~~~~~
../dist/include/mozilla/TypeTraits.h:81:25: error: unknown template name 'IsVoidHelper'
struct IsVoid : detail::IsVoidHelper<typename RemoveCV<T>::Type> {};
                        ^
../dist/include/mozilla/TypeTraits.h:81:47: error: expected a qualified name after 'typename'
struct IsVoid : detail::IsVoidHelper<typename RemoveCV<T>::Type> {};
                                              ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
/nidium/Nidium/third-party/.default/mozilla-central/config/rules.mk:956: recipe for target 'Compression.o' failed
make[3]: *** [Compression.o] Error 1
make[3]: Leaving directory '/nidium/Nidium/third-party/.default/mozilla-central/js/src/obj/mfbt'
/nidium/Nidium/third-party/.default/mozilla-central/config/recurse.mk:71: recipe for target 'mfbt/target' failed
make[2]: *** [mfbt/target] Error 2
make[2]: *** Waiting for unfinished jobs....

the system I used

root@b9db9671b284:/nidium/Nidium# cat /proc/version
Linux version 4.4.27-moby (root@1d811a9194c4) (gcc version 5.3.0 (Alpine 5.3.0) ) #1 SMP Wed Oct 26 14:21:29 UTC 2016
root@b9db9671b284:/nidium/Nidium# cat /etc/issue
Debian GNU/Linux 8 \n \l

root@b9db9671b284:/nidium/Nidium# cat /etc/debian_version
8.6
root@b9db9671b284:/nidium/Nidium#

Framebuffer fatal error on 'console.show'

Accourding to the autotests the following example causes a fatal error.

Console.static_methods.Console.show.0

Entering inside function TestsRunner.prototype._nextTest/<
Entering inside function anonymous
fbo fatal error 8cd6
[DEBUG ] Command result:
	Code: 1 

[ERROR ] Unit tests failed :(

How to start sub- or helper-processes?

I found the NiridiumProcess API but it seems to only explain the main process object of the runtime.

Is there a way to start a subprocess, like say, /usr/bin/my-helper do-something-native when being inside the Niridium context?

I also took a look at the Thread API, but they seem to be only ES-function based so I guess they can't interact with other processes either.

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.