Code Monkey home page Code Monkey logo

sval's Introduction

Sval · npm github-actions coveralls

A JavaScript interpreter writen in JavaScript, based on parser Acorn.

  • Running on ES5, supporting ES5~10 full features
  • Both invasived and sandbox modes available

It's useful to evaluate the code of higher ECMAScript editions, or for the environment with disabled eval, setTimeout and new Function.

Try Sval on the playground.

Installation

Node

Install Sval with npm.

npm install sval

Browser

Simply source from unpkg. Or, download from releases, get minimized file dist/min/sval.min.js, and source at your html page. You can access a global variable Sval directly.

<script type="text/javascript" src="https://unpkg.com/sval"></script>

Usage

import Sval from 'sval'

// Sval options
const options = {
  // ECMA Version of the code (5 | 6 | 7 | 8 | 9 | 10 | 2015 | 2016 | 2017 | 2018 | 2019)
  ecmaVer: 9,
  // Whether the code runs in a sandbox
  sandBox: true,
}

// Create a interpreter
const interpreter = new Sval(options)

// Add global modules in interpreter
interpreter.import('importWhatYouNeed', 'AllKindsOfStuffs')
// Or interpreter.import({ importWhatYouNeed: 'AllKindsOfStuffs' })

// Parse and run the code
interpreter.run(`
  const msg = 'Hello World'
  exports.msg = msg // Export any you want
`)

interpreter.run(`
  exports.mod = importWhatYouNeed // Export again and merge
`)

// Get exports from runs
console.log(interpreter.exports.msg) // Get 'Hello World'
console.log(interpreter.exports.mod) // Get 'AllKindsOfStuffs'

Sval constructor has options with two fields, ecmaVer and sandBox.

  • ecmaVer is the ECMAScript edition of the code. Currently, 5, 6(2015), 7(2016), 8(2017), 9(2018) and 10(2019) are supported, and the default edition is 9.

  • sandBox is true for sandbox mode or false for invasived mode. Sandbox mode will run code in an isolated sandbox and won't pollute your global scope. Invasived mode allows you run code in the same global scope of your current environment. The default setting is true.

Sval instance has three methods, import, parse and run.

  • import is to import modules into your Sval instance scope, expecting a name and a module as arguments like import(name: string, mod: any), or an object which contains the modules as argument like import({ [name: string]: any }). The modules will be automatically declared as global variables. This method is more likely to be used in sandbox mode.

  • parse is to parse the code with internal Acorn or custom parser, to get the corresponding AST, like parse(code: string) or parse(code: string, parser: (code: string, options: SvalOptions) => estree.Node

  • run is to evaluate the code inputed, expecting a string as argument like run(code: string), or an AST followed ESTree Spec as argument like run(ast: estree.Node). If you want to export something, there is a internal global exports object for mounting what you want to export.

Sval instance also has a field, exports, to get what you exported from runs, merged if several runs have exports.

Note

WithStatement and LabeledStatement aren't implemented and recommended. Please avoid to use them.

Reference

License

Sval is licensed under the MIT.

sval's People

Contributors

bloody-ux avatar dependabot[bot] avatar llorx avatar siubaak 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

sval's Issues

Bug of hoisting function

Function hoisting sometimes causes a bug of calling bind method of undefined. Figure out later.

Can't access variable inside function

Demo:

console.log('Sval Version: ' + Sval.version)

const interpreter = new Sval()

interpreter.run(`
const tryValue = (x) => {
console.log(\`value of ${x}\`);
}
tryValue('xxxx');
`)

console.log('End: ' + interpreter.exports.end)

x has no value inside function

global variable should be set with configurable: false

In javascript, when a variable is declared in global scope, it will be set to global object as member with configurable: false as well. Sval doesn't follow this rule thoroughly.

Test case:

const Sval = require('sval')
const interpreter = new Sval({ ecmaVer: 8 })

interpreter.run(`
    var x = 4;

    console.log('configurable?: ', Object.getOwnPropertyDescriptor(window, 'x').configurable);
    console.log('in operator?:', 'x' in window); // correct
    console.log('before deleting:', x)
    console.log('deleted by window.x?:', delete window.x); // incorrect
    console.log('after deleted:', x)

    exports.end = true;
`)

module.exports = 'End: ' + interpreter.exports.end

Expected result:

configurable?:  false
in operator?: true
before deleting: 4
deleted by window.x?: false
after deleted: 4

Actual result:

configurable?:  true
in operator?: true
before deleting: 4
deleted by window.x?: true
after deleted: 4

Cause:
image

Maybe it should be changed to something like this:

Object.defineProperty(win, name, {
   value,
   writable: true,
   enumerable: true,
   configurable:false, // can omit
});

Informative error messages

With the this const x = 2; x = 4;; With the demo page you get this error:

"st</e.prototype.set@https://unpkg.com/sval:1:93759
AssignmentExpression@https://unpkg.com/sval:1:101042
Nt@https://unpkg.com/sval:1:108758
ExpressionStatement@https://unpkg.com/sval:1:104758
Nt@https://unpkg.com/sval:1:108758
Program@https://unpkg.com/sval:1:108654
Nt@https://unpkg.com/sval:1:108758
e.prototype.run@https://unpkg.com/sval:1:143538
@kehahiqono.js:28:13
"

Running the same code in the browser you get this error: TypeError: invalid assignment to const x'`.

The browser error is more informative.

Is there a way to get error messages similar to that in the browser?

forX with variable declaration doesn't work since 0.3.1

There's a break change for forX since [email protected], below is the test case:

const Sval = require('sval')

const interpreter = new Sval({ ecmaVer: 8 })

interpreter.run(`
  const x = [1,2];
  for(var xx of x) console.log(xx)
  for(var xx in x) console.log(xx)
  exports.end = true
`)

module.exports = 'End: ' + interpreter.exports.end

Expected result:

1
2
0
1

Actual result:

undefined
undefined
undefined
undefined

While below test case works great:

const Sval = require('sval')

const interpreter = new Sval({ ecmaVer: 8 })

console.log(Sval.version);

interpreter.run(`
  const x = [1,2];
  var xx;
  for(xx of x) console.log(xx)
  for(xx in x) console.log(xx)
  exports.end = true
`)

module.exports = 'End: ' + interpreter.exports.end

It looks like forX deals with VariableDeclaration incorrectly.
And this new issue is caused when fixing this issue

Support for dynamic imports of ES modules

Hey, nice tool you've got here. I'm using it in a project I'm working on. I was trying to see if I could use the new dynamic imports in the demo jsbin but got an error:

SyntaxError: 'import' and 'export' may appear only with 'sourceType: module'.

Do I need to do something special to get it to work? Or is it the environment setup I should be looking at? (since I believe it needs me to use a <script type="module"></script>)

simulate temporal dead zone of let and const

test case:

const s = require('./dist/sval')

const i = new s

i.run(`
const a = 1
{
  console.log(a) // dead
  const a = 2
  console.log(a)
}
`)

expected:

ReferenceError: a is not defined

actual:

1
2

fail to run js code

Thanks for your work!

When I tried to run a piece of code, I got SyntaxError: Identifier 'a' has already been declared.

And I tried all ecmaVer.

Here is the code: jsbin

Serializable interpreter?

Hello there,

This library is quite useful, thanks and really a good job.
I was wondering if it's possible with sval to serialize the interpreter, store it, deserialize it later, and resume the execution. Even if there are some limitation, the idea would be to use it like a state machine. It's quite useful for debug and testing (branch, rollback execution, ...)

I know JS interpreter has this feature, but the lack of modern ECMA (es5 only) makes it really hard to use compared to sval.

How to get the result of expression?

I want to execute:

interpreter.run('var x = 10;');
interpreter.run('x');

so how to get the output of expression? Note I have no idea what the value is I want to build a REPL. That will work with:

interpreter.run('let x = 10;');
interpreter.run('x');

because eval runs in strict mode when using let and code is in a block.

ret missing in arrow functions

I found a small issue with arrow functions. They should return something without an explicit return if you pass an expression instead of a block:

"use strict";
const Sval = require("sval");
const js = new Sval({ ecmaVer: 9, sandBox: true });

js.run(`
	const base = 40;
	exports.answer = x => base + x;
	//exports.answer = x => { return base + x };
`);

console.log(js.exports.answer(2));
// undefined

Anyway, great library! I really like how simple the compiler and bytecode interpreter are. It's a great starting point for learning how javascript engines work.

Switch 逻辑好像有点问题

interpreter.run(`
 	function test(t) {

       switch (1) {
           case 1:
               console.log('test1')
               break;
       }

       console.log('test2')

       return 'test3'
   }

   console.log(test())
`)

// test1
// undefined

看了一下源码,好像遇到 break 不应该把状态 return 出去

export function SwitchStatement(node: estree.SwitchStatement, scope: Scope) {
  const discriminant = evaluate(node.discriminant, scope)
  let matched = false
  for (let i = 0; i < node.cases.length; i++) {
    const eachCase = node.cases[i]
    if (
      !matched
      && (
        !eachCase.test  // default
        || (evaluate(eachCase.test, scope)) === discriminant
      )
    ) {
      matched = true
    }
    if (matched) {
      const result = SwitchCase(eachCase, scope)
      if (result === BREAK || result === CONTINUE || result === RETURN) {
        return result
      }
    }
  }
}

改成下面这样运行就没问题了

export function SwitchStatement(node: estree.SwitchStatement, scope: Scope) {
  const discriminant = evaluate(node.discriminant, scope)
  let matched = false
  for (let i = 0; i < node.cases.length; i++) {
    const eachCase = node.cases[i]
    if (
      !matched
      && (
        !eachCase.test  // default
        || (evaluate(eachCase.test, scope)) === discriminant
      )
    ) {
      matched = true
    }
    if (matched) {
      const result = SwitchCase(eachCase, scope)
      if (result === BREAK) {
        break
      }
      if (result === CONTINUE || result === RETURN) {
        return result
      }
    }
  }
}

super call expression throw exception

super.xxxx() doesn't work(with latest version of sval), below is an example:

const Sval = require('sval')

const interpreter = new Sval({ ecmaVer: 10 })

console.log(Sval.version);

interpreter.run(`
  class X{
    say() {
      console.log('X') 
    }
  }

  class Y extends X {
    say() {
      super.say(); 
      console.log('Y')
    }
  }

  const i = new Y();
  i.say();

  exports.end = true;
`)

module.exports = 'End: ' + interpreter.exports.end

Expected resut:

X
Y

Actual result:

throw exception: TypeError: Cannot read property 'get' of null

function Super(node, scope, options) {
      if (options === void 0) { options = {}; }
      var _a = options.getProto, getProto = _a === void 0 ? false : _a;
      var superClass = scope.find(SUPER).get();  // can't find super object
      return getProto ? superClass.prototype : superClass;
  }

toString method doesn't return correct value for funtion

Function.prototype.toString should return original source of the function, but sval returns cooked one.

Test case:

const Sval = require('sval')

const interpreter = new Sval({ ecmaVer: 8 })

interpreter.import({
  getItem: n => new Promise(resolve => setTimeout(resolve, 1500, n))
})

interpreter.run(`
  var f = function() {};
  console.log(f.toString());
  
  var o = {};
  console.log(o.toString());
  
  var arr = [1,2];
  console.log(arr.toString());
  
  exports.end = true;
`)

module.exports = 'End: ' + interpreter.exports.end

Expected result:

"function() {}"
"[object Object]"
"1,2"

Actual result:

"function () {\r\n                    var args = [];\r\n   …d([tmpGenerator.bind(this)], args));\r\n                }"
"[object Object]"
"1,2"

To correct this, we need to override toString method for functions, but it will cause another test case failed:

(function(){}).toString === Function.prototype.toString

It's a hard decision.

Module support

I am working on a desktop simulation for the browser. I would really want module support to be added to sval. I need to import two libraries in my files. I also need the run the files in sandbox. My current workaround is exporting a function to, later on, be called with the modules inside a parameter.

Migrate tests to typescript with `ts-jest`

Test cases are written in javascript and it depends on dist, which causes 3 issues:

  1. coverage data is not clear for each module, only shows sval.js
  2. need to run start, before running test, and it's easy to forget to run start script.
  3. no intellisense support when writing test cases.

I will give a PR later.

ReferenceError xxx is not defined

运行如下代码

const interpreter = new Sval()
interpreter.run(`
const a = 1;
function say() {
  console.log(a);
}
say();
`)

会得到 ReferenceError a is not defined

Setting time-bound on execution of code

I am looking to use Sval in an educational context and would like to know if there is any way to set a time-bound on how long the evaluated code can run for? This would be helpful if the evaluated code has an infinite loop.

An older project (JS-Interpreter) handles this use case "by calling the step function a maximum number of times, or by calling step indefinitely many times but using a setTimeout between each call to ensure other tasks have a chance to execute". I wonder if there's something I can do in Sval like this?

[Discussion] tests should be js or ts extension

I found all tests have ts extension now, it will lead to issues:

1、 vscode extension Jest will not work correctly
2、 Invalid test data provided to test case will report ts error in editor.

image

hi, regular expression parse error

test code:
interpreter.run('var s =/(^ws://)/;')

The following error occurs:

SyntaxError: Invalid regular expression: /(^ws:/: Unterminated group (1:8)
at Parser.pp$4.raise (c:\Users\Administrator\node_modules\acorn\dist\acorn.js:2757:13)
at RegExpValidationState.raise (c:\Users\Administrator\node_modules\acorn\dist\acorn.js:3530:15)
at Parser.pp$9.regexp_eatCapturingGroup (c:\Users\Administrator\node_modules\acorn\dist\acorn.js:3841:11)
at Parser.pp$9.regexp_eatExtendedAtom (c:\Users\Administrator\node_modules\acorn\dist\acorn.js:3853:10)
at Parser.pp$9.regexp_eatTerm (c:\Users\Administrator\node_modules\acorn\dist\acorn.js:3703:57)
at Parser.pp$9.regexp_alternative (c:\Users\Administrator\node_modules\acorn\dist\acorn.js:3684:50)
at Parser.pp$9.regexp_disjunction (c:\Users\Administrator\node_modules\acorn\dist\acorn.js:3668:8)
at Parser.pp$9.regexp_pattern (c:\Users\Administrator\node_modules\acorn\dist\acorn.js:3641:8)
at Parser.pp$9.validateRegExpPattern (c:\Users\Administrator\node_modules\acorn\dist\acorn.js:3617:8)
at Parser.pp$8.readRegexp (c:\Users\Administrator\node_modules\acorn\dist\acorn.js:4941:8)

`finally` always returns value

Sval doesn't deal with finally statement correctly, it doesn't check whether there's RETURN value before return, which leads below case failed.

Test case:

const Sval = require('sval')

const interpreter = new Sval({ ecmaVer: 8 })

interpreter.run(`
    function T() {
      try {
        return 7;
      } catch (ex) {
        return 5;
      } finally {
        
      }
    }

    console.log(T());
    exports.end = true;
`)

module.exports = 'End: ' + interpreter.exports.end

Expected result:

7

Actual result:

undefined

Cause: always returns value. needing to check whether there's a RETURN.

image

Unexpected behaviour with promises (Bug?)

Hi again.
I am running into a problem when using Promises.
Here are two cases:

// Case 1
fs.openFileDialog('template.txt').then(()=>{
  console.log('then');
});    

// Case 2
let promise = fs.openFileDialog('template.txt');
promise.then(()=>{
  console.log('then');
});

Case 1 fails. It actually executes the async functions twice (fs.openFileDialog('template.txt')). So I get two open-file-dialogs at once.

Case 2 works without any problems.

Is this a known bug?
Thanks in advance...

Use meriyah vs acorn

Meriyah is faster, compiles to the same AST as acorn and also supports future ES specs, so should be easy to move from one to the other.

I think is a good option to move from one to the other: https://github.com/meriyah/meriyah

Benchmarks: https://meriyah.github.io/meriyah/performance/ (cold test fails when reaching jquery mobile because of a 404 error).

EDIT: Just changed acorn to meriyah and works out of the box, without any special addition. One problem is that the options object is different, but the performance improvement is incredible.

Maybe we can pass our own "parser" and select meriyah, acorn or even esprima (just pass a parse function option which should return an AST tree) or something like that.

PD: I've tested it with my own scripts and works 100%. Meriya has a lot of options disabled by default (like locations and raws) so I don't know what you actually need for it to work 100%.

How safe is this interpreter?

I need to run some external code on my app. I'm mostly concerned that this external code can access localstorage and cookies. Can the interpreter do that? Is there a way to disable certain APIs like localstorage, eval etc?
Thank you!

better stack traces

It would be nice if errors created and thrown by code running via sval could have better stack traces. Below I've shared an approach I used in a POC. All the information to create rich stack traces is available. I suspect it's even possible to have stack traces that combine traces from scripts within sval and scripts outside (i.e. when an outside script calls an inside script and vice-versa)

ast is being modified by hoist

Is there a way to avoid ast modification? Because my code runs pretty slow because of multiple acorn.parse, so I created a single ast by running acorn.parse one time and run the same ast multiple times. That's what I do in JS-Interpreter and is pretty viable as ast is not modified in any way, but keeping all the state in a different object (which I delete or recycle, depending on situations).

I like this interpreter a lot, but I'm having problems implementing it as it always need a new ast, which I create with another acorn.parse, because the ast is modified while running, so here "ast caching" is not viable. This makes this interpreter way way slower than JS-Interpreter (actually sval is way faster when interpreting the JS (about 8 times), but globally is slower if you do a lot of runs with the same code).

Arrow function should have isolated scope

A new isolated scope should be created for arrow function, but sval doesn't follow this rule.

Test case:

const Sval = require('sval')

const interpreter = new Sval({ ecmaVer: 8 })

interpreter.run(`
(function x() {
  var y = 'outer-value';

  var arrowFunc = () => {
    var y = 'inner-value';
    console.log('inner', y);
  }

  arrowFunc();
  console.log('outer:', y);
})()
`)

module.exports = 'End'
})()

Expected result:

"inner"
"inner-value"
"outer:"
"outer-value"
"End"

Actual result:

"inner"
"inner-value"
"outer:"
"inner-value"
"End"

The cause is arrow function should have isolated function scope as regular function, but sval doesn't.

image

Arrow func vs regular func:

  • this is bound to the one of its creation time.
  • can't be a constructor, will throw error
  • arguments is not available
  • yield expression is not allowed, means can't be a generator function.

循环语句中的switch break会导致出错

遇到switch条件中的break会直接跳出循环,测试代码如下:

var i = 0; while (i < 10) { console.log(i); i++; switch (2) { case 2: break; } }

只打印 0 即退出。

将 function SwitchStatement 中
if (result === BREAK || result === CONTINUE || result === RETURN) { return result; }

部分改成

if (result === BREAK) { break; } if (result === CONTINUE || result === RETURN) { return result; }

可破,但是不确定是否会引入其他问题,麻烦更新下。

let [ , x, y] = [1, 2, 3] 解析有问题

let [ , x, y] = [1, 2, 3]

这个语句解析会报错

/src/evaluate/pattern.ts里面的ArrayPattern方法有问题
node.elements数组里面存的值有可能是null

export function* ArrayPattern(node: estree.ArrayPattern, scope: Scope, options: PatternOptions = {}) {
  const { kind, hoist = false, feed = [] } = options
  const result = []
  for (let i = 0; i < node.elements.length; i++) {
    const element = node.elements[i]
    if (hoist) {
      if (kind === 'var') {
        if (element.type === 'Identifier') {
          scope.var(element.name)
        } else {
          yield* pattern(element, scope, { kind, hoist })
        }
      }
    } else {
      if (element.type === 'Identifier') {
        if (kind) {
          // If kind isn't undefined, it's a declaration
          scope[kind](element.name, feed[i])
        } else {
          // If kind is undefined, it's a statement
          const variable: Var = yield* Identifier(element, scope, { getVar: true })
          variable.set(feed[i])
          result.push(variable.get())
        }
      } else if (element.type === 'RestElement') {
        yield* RestElement(element, scope, { kind, feed: feed.slice(i) })
      } else {
        yield* pattern(element, scope, { kind, feed: feed[i] })
      }
    }
  }
  if (result.length) {
    return result
  }
}

es6 supported

Support all es6 features, like arrow function, let/const declaration, class declaration and so on.

variable re-declaration doesn't work correctly

When a variable is declared more than one time, and initial value is undefined, the default assignment won't take effect.

Test case:

const Sval = require('sval')

const interpreter = new Sval({ ecmaVer: 8 })

interpreter.run(`
  var x = 5;
  var x = undefined;
  console.log(x)
  exports.end = x
`)

module.exports = 'End: ' + interpreter.exports.end

Expeceted output: undefined
Actual output: 5

image

The cause:
image

小程序热更新问题

`const Sval = require('sval')
const interpreter = new Sval()

interpreter.import({ Page, wx, app: getApp() })
interprete.run(Page({ data: {}, onShow() {}, customMethod() {} }))`

小程序使用此方法做热更新时,若脚本字符串为异步获取,需要在此页面打开之前获取到代码,否则会导致页面注册失败、

performance issue for 'loop'

For below test case, with iterations increasing, the program runs slower and slower.
It seems each iteration needs a re-parsing to execute.

Under node 11.13.0, If iterations is 1, it costs 1.74ms, while 0.225ms running natively. If iterations is 100000, it costs 1443ms, while 3.59ms running natively.

If the code runs natively,

const Sval = require('sval');


const interpreter = new Sval({ ecmaVer: 8, sandBox: true });

interpreter.run(`
var x = 0;
function functionOne() {
  x++;
}

var iterations = 100000;
console.time('Function #1');
for(var i = 0; i < iterations; i++ ){
    functionOne();
};
console.timeEnd('Function #1')

exports.result=x;
`);

console.log(interpreter.exports.result);

hoisting of var and function

Currently sval is running like a repl mode, so the var and function declaration will not be hoisted. To meet the requestment of ecma standard, if creating a function scope, scan the whole function body to make all var and function declarations in non-function body firstly.

implement stack-based interpreter to improve performance

currently sval is a tree-walking interpreter and has a ordinary performance. compile the code into some kinds of intermediate representation based on stack to improve performance.

I have a demo as followed. it may be difficult and take some time to migrate.

const { parse } = require('acorn')
const { simple } = require('acorn-walk')

const ast = parse('1 + 8 * 2 / 2 + 1')

const stack = []

simple(ast, {
  Literal(node) {
    stack.push(node.value)
  },
  BinaryExpression(node) {
    const right = stack.pop()
    const left = stack.pop()
    const binaryOps = {
      '+': () => left + right,
      '-': () => left - right,
      '*': () => left * right,
      '/': () => left / right
    }
    const handler = binaryOps[node.operator]
    if (handler) {
      stack.push(handler())
    } else {
      throw new SyntaxError(`Unexpected token ${node.operator}`)
    }
  }
})

console.log(stack[0])

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.