Coder Social home page Coder Social logo

icsharpcode / ilspy Goto Github PK

View Code? Open in Web Editor NEW
20.2K 711.0 3.2K 41.12 MB

.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!

C# 99.50% Batchfile 0.02% F# 0.02% PowerShell 0.17% Visual Basic .NET 0.19% Jupyter Notebook 0.10% Shell 0.01%
decompiler decompiler-engine c-sharp dotnet dotnetcore mono unity pdb ilspy decompile

ilspy's People

Contributors

arturek avatar bbi-yggyking avatar chicken-bones avatar christophwille avatar cshung avatar dependabot[bot] avatar dgrunwald avatar dsrbecky avatar dymanoid avatar edharvey avatar edkazcarlson avatar elektrokill avatar eusebiu avatar jbevain avatar linquize avatar lordjz avatar ltrzesniewski avatar maikebing avatar miloush avatar mohe2015 avatar ondrejpetrzilka avatar pentp avatar rklier avatar rpinski avatar sharwell avatar siegfriedpammer avatar slaks avatar tom-englert avatar wwh1004 avatar yyjdelete 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

ilspy's Issues

Incorrect decompile of a NaN or +/-Infinity literal.

System.Double.NaN decompiles to the following code:
public const double NaN = NaN.0;

Obviously that will not compile. There are similar issues for System.Double.PositiveInfinity, and System.Double.NegativeInfinity.

Instead NaN is best represented as 0.0/0.0.

The C# 4.0 compiler will compile that into a NaN that is bit-for-bit identical to System.Double.NaN.

Similarly PositiveInfinity is best represented as 1.0/0.0, and NegativeInfinity as -1.0/0.0.
Those expressions also compile bit for bit identical to the System.Double members.

ICSharpCode.Decompiler.DecompilerException: Error decompiling System.Void System.Decimal::.cctor()

mscorlib
System.Decimal:

---> System.InvalidCastException: Cast from Int64 to Boolean not supported.

must be

static Decimal()
{
Powers10 = new uint[] { 1, 10, 100, 0x3e8, 0x2710, 0x186a0, 0xf4240, 0x989680, 0x5f5e100, 0x3b9aca00 };
Zero = 0M;
One = 1M;
MinusOne = -1M;
MaxValue = 79228162514264337593543950335M;
MinValue = -79228162514264337593543950335M;
NearNegativeZero = -0.000000000000000000000000001M;
NearPositiveZero = 0.000000000000000000000000001M;
}

Conditional boolean return

ILSpy 1.0.0.427 gives the following for System.Double.IsNaN():
public static bool IsNaN(double d)
{
if (d != d)
{
return true;
}
return false;
}

That decompilation is entirely correct, but it is subobptimal. It would be better as a one liner like reflector gives:
public static bool IsNaN(double d)
{
return (d != d);
}

The pattern matching should also be able to handle returning the negation of the condition, for cases of the form "if(...) return false; else return true;".

deadlock

mscorlib
namespace System.Globalization
class TimeSpanParse.

Attributes are missing

I cannot see the attributes used in classes neither members. Is this a bug? or, can this be a feature to add?

passing null to a method/constructor that has multiple signatures

When the method has multiple signatures; such as foo(MyObject o) and foo(string s), then code calling for with a null argument must have a cast. Currently ILSpy will display foo(null) and it should be foo((string) null) or foo((MyObject) null).

I found this while looking at the .ctor for System.Xml.Resolvers.XmlPreloadedResolver.

Feature Request: IL Opcode tooltips

Reflector provides convenient tooltips when hovering over an IL opcode, describing the opcode and giving the hexadecimal value of it. The descriptions are taken from the xml documentation summary tags for the corresponding fields in the System.Reflection.Emit.OpCodes class.

Please consider adding such tooltips once you have support for loading and displaying the xml documentation for an assembly.

C# null check is wrong

C# null checks are decompiled as :
if(instance)
{
instance.Dispose();
}
Correct should be
if (instance != null)

Decompilation of inline comparisons into a 'flag' variable done wrong.

For instance:

for (int current = 0; ; )
{
    bool flag = current < 100; //<----- note this 'flag' variable created automatically by the decompiler
    if (!flag)
    {
        break;
    }
    else
    {
        this.DoSomething();
        current += 1;
    }
}

List<int> list = new List<int>();
list.Add(1);
list.Add(2);
flag = (list == null); //<----- the same 'flag' used again, although not in scope.
if (!flag)
{
    this.DoSomething();
}

Attribute the loss of 'extern'

mscorlib v.4.0
Microsoft.Win32.OAVariantLib

private static void ChangeTypeEx(Variant result, Variant source, int lcid, IntPtr typeHandle, int cvType, short flags);

should be

private static extern void ChangeTypeEx(Variant result, Variant source, int lcid, IntPtr typeHandle, int cvType, short flags);

ldelem.any

class MyArray<T> where T : new()
{
    private T[] arr;

    public MyArray()
    {
        this.arr = new T[20];
    }

    public MyArray(int capacity)
    {
        this.arr = new T[capacity];
    }

    public void Size(int capacity)
    {
        T[] destinationArray = new T[capacity];
        Array.Copy(this.arr, destinationArray, this.arr.Length);
        this.arr = destinationArray;
    }

    public void Grow(int capacity)
    {
        if (capacity >= this.arr.Length)
        {
            this.Size(capacity + 1);
        }
        if (this.arr[capacity] == null) 
        {
            this.arr[capacity] = new T();
        }
    }
}

public void Grow(int capacity)
{
if (capacity >= this.arr.Length)
{
base.Size(capacity + 1); <===============
}
if (ldelem.any(T, this.arr, capacity) == null) <===========
{
T[] arg_5F_0 = this.arr; <==== new T();
int arg_5F_1 = capacity;
T t = default(T);
T arg_5F_2;
if (t == null)
{
arg_5F_2 = Activator.CreateInstance();
}
else
{
t = default(T);
arg_5F_2 = t;
}
arg_5F_0[arg_5F_1] = arg_5F_2;
}
}

Wrong static System.Decimal()

mscorlib
System.Decimal

static Decimal()
{
uint[] expr_07 = new uint[10];
Array arg_0D_0 = expr_07;
uint[] arg_12_0 = expr_07;
RuntimeHelpers.InitializeArray(arg_0D_0, ldtoken($$method0x6006097-1));
decimal.Powers10 = arg_12_0;
decimal.Zero = new decimal(0);
decimal.One = new decimal(1);
decimal.MinusOne = new decimal(-1);
decimal.MaxValue = new decimal(-1, -1, -1, false, 0);
decimal.MinValue = new decimal(-1, -1, -1, 128 != 0, 0);
decimal.NearNegativeZero = new decimal(1, 0, 0, 128 != 0, 27);
decimal.NearPositiveZero = new decimal(1, 0, 0, false, 27);
}

must be

static Decimal()
{
Powers10 = new uint[] { 1, 10, 100, 0x3e8, 0x2710, 0x186a0, 0xf4240, 0x989680, 0x5f5e100, 0x3b9aca00 };
Zero = 0M;
One = 1M;
MinusOne = -1M;
MaxValue = 79228162514264337593543950335M;
MinValue = -79228162514264337593543950335M;
NearNegativeZero = -0.000000000000000000000000001M;
NearPositiveZero = 0.000000000000000000000000001M;
}

'for' loops decompiled wrong

The decompiled version of this:

    public void ForLoopTest()
    {
        for (int i = 0; i < 100; ++i)
        {
            DoSomething();
        }
    }

is this:

public void ForLoopTest()
{
for (int i = 0; ; )
{
if (i >= 100) // should be placed after first semicolon
{
break;
}
else
{
this.DoSomething(); // redundant 'this.'
i += 1; // can be changed to ++i or i++ and placed after second semicolon
}
}
}

StackBefore == null

Ln 207 if (branchTarget.StackBefore.Count != newStack.Count) // is true

Ln 233 int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count; // StackBefore == null

Ln 384 int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count; // StackBefore == null

Invalid stind/ldind

class Class1
{
    private int i = 0;
    public void method(out string str)
    {
        str = "qq";
        str += i.ToString();
    }
}

public void method(out string str)
{
str = "qq";
string expr_09 = ref str;
string arg_0A_0 = expr_09;
stind.ref(expr_09, ldind.ref(arg_0A_0) + this.i.ToString());
}

redundant explicit boxing

double num = 12.345;
double num2 = 12.0;
Console.WriteLine("{0:#.#} {1:#.#}", box(System.Double, num), box(System.Double, num2));

Notice the unnecessary box(...) instructions around num and num2.

typo in test runner

ICSharpCode.Decompiler/Tests/TestRunner.cs line 75

        while ((line2 = r2.ReadLine()) != null) {
            ok = false;
  •           diff.WriteLine("+" + line1);
    
  •           diff.WriteLine("+" + line2);
        }
    

StackOverflow in C# decompiler

Hey,
I've got the latest sources and I tried to decompile the SearchBox from ILSpy and ILSpy crashed...

When debugging I got this error:
Can not intercept exception. Debugged program can not be continued and properties can not be evaluated.
System.StackOverflowException
at Object Decompiler.Transforms.PushNegation.VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, Object data) in e:\ILSpy\ICSharpCode.Decompiler\Ast\Transforms\PushNegation.cs:line 80
at Object ICSharpCode.NRefactory.CSharp.BinaryOperatorExpression.AcceptVisitor(IAstVisitor2 visitor, Object data) in e:\ILSpy\NRefactory\ICSharpCode.NRefactory\CSharp\Ast\Expressions\BinaryOperatorExpression.cs:line 72 at Object Decompiler.Transforms.PushNegation.VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, Object data) in e:\ILSpy\ICSharpCode.Decompiler\Ast\Transforms\PushNegation.cs:line 86 at Object ICSharpCode.NRefactory.CSharp.BinaryOperatorExpression.AcceptVisitor(IAstVisitor2 visitor, Object data) in e:\ILSpy\NRefactory\ICSharpCode.NRefactory\CSharp\Ast\Expressions\BinaryOperatorExpression.cs:line 72
at Object Decompiler.Transforms.PushNegation.VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, Object data) in e:\ILSpy\ICSharpCode.Decompiler\Ast\Transforms\PushNegation.cs:line 86
at Object ICSharpCode.NRefactory.CSharp.BinaryOperatorExpression.AcceptVisitor(IAstVisitor2 visitor, Object data) in e:\ILSpy\NRefactory\ICSharpCode.NRefactory\CSharp\Ast\Expressions\BinaryOperatorExpression.cs:line 72 at Object Decompiler.Transforms.PushNegation.VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, Object data) in e:\ILSpy\ICSharpCode.Decompiler\Ast\Transforms\PushNegation.cs:line 86 at Object ICSharpCode.NRefactory.CSharp.BinaryOperatorExpression.AcceptVisitor(IAstVisitor2 visitor, Object data) in e:\ILSpy\NRefactory\ICSharpCode.NRefactory\CSharp\Ast\Expressions\BinaryOperatorExpression.cs:line 72

redundant ctor

in a class without a ctor, ILSpy shows this:

public() : base()
{
}

try {} catch problem

method()
{
try
{
try
{ }
finaly()
{ }
// leave to return
}
catch()
{ }

}

FILE: ILAstBuilder.cs

List StackAnalysis(MethodDefinition methodDef)
{
Ln 207 // if (branchTarget.StackBefore.Count != newStack.Count) <-- is true
Ln 233 // int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count; <-- StackBefore == null
}

List ConvertToAst(List body)
{
Ln 364 // int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count; <-- StackBefore == null
}

typing gone wrong

Found this code when browsing ILSpy code on ILSpy:

function path: ILSpy/ICSharpCode.ILSpy/CSharpLanguage/d__7

  • look at typing of arg_22_0
  • in addition it has gone out of scope in 2nd assignment and in test

private IEnumerator System.Collections.Generic.IEnumerable<ICSharpCode.ILSpy.CSharpLanguage>.GetEnumerator()
{
if (Thread.CurrentThread.ManagedThreadId == this.<>l__initialThreadId)
{
var arg_22_0 = this.<>1__state == -2 == 0; // <<< assinged bool
}
else
{
arg_22_0 = 1; // <<< assigned int
}
if (arg_22_0 == null) // <<< compared to pointer
{
this.<>1__state = 0;
CSharpLanguage.d__7 d__7 = this;
}
else
{
d__7 = new CSharpLanguage.d__7(0);
}
IEnumerator enumerator = d__7;
return enumerator;
}

request for generating default in switch

Some times the generated code has many gotos because code from defaults is not identified here is an example:

input:

public static int Switch(int i)
{
    int j;
    switch (i)
    {
        case 0:
        {
            j = i + 1;
            break;
        }
        case 1:
        {
            j = i + 2;
            break;
        }
        default:
        {
            return -1;                  
        }
    }
    return j * 2;
}

output:

public static int Switch(int i)
{
    int j;
    switch (i)
    {
        case 0:
        {
            j = i + 1;
            goto IL_20;
        }
        case 1:
        {
            j = i + 2;
            goto IL_20;
        }
    }
    return -1;
    IL_20:
    return j * 2;
}

"Check for updates" fails behind a web proxy

"Check for updates" does not support web-proxy. If PC requires a web-proxy to connect to the internet, the check fails with an exception:

System.AggregateException: One or more errors occurred. ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: Impossibile stabilire la connessione. Risposta non corretta della parte connessa dopo l'intervallo di tempo oppure mancata risposta dall'host collegato 195.234.231.66:80
at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult)
.... [SNIP] ....

System.InvalidCastException: Cast from Int64 to Boolean not supported.

at ICSharpCode.NRefactory.Utils.CSharpPrimitiveCast.CSharpPrimitiveCastUnchecked(TypeCode targetType, Object input)
at Decompiler.AstMethodBodyBuilder.MakePrimitive(Int64 val, TypeReference type)
at Decompiler.AstMethodBodyBuilder.TransformByteCode(ILExpression byteCode, List`1 args)
at Decompiler.AstMethodBodyBuilder.TransformExpression(ILExpression expr)
...

IL_005a: ldloc.2
IL_005b: ldfld class RSClient_I32.__CallBackClass_busChangedEventHandler class RSClient_I32.__CallBackClass_SinkHelper::m_busChangedDelegate
IL_0060: ldarg <-------------- ldarg 1
IL_0064: castclass object
IL_0069: callvirt instance bool [mscorlib]System.Delegate::Equals(object)
IL_006e: ldc.i4 255 <----------- System.InvalidCastException
IL_0073: and
IL_0074: ldc.i4 0
IL_0079: beq IL_00d4

enum value looses type when boxed

Console.WriteLine("{0} $$ {1}", AttributeTargets.Class, AttributeTargets.Field | AttributeTargets.Property);

Should print:
Class $$ Property, Field

but prints
Class $$ 384

I prepared a fix for this issue (see parts of commit arturek/ILSpy@679d525806d8ca7c0820) as a part of my work on custom attribute support but I am still working on some other issues related to it (and on validation of correctness of this change). I can notify you when I finish if you are interested in it.

initobj(...)

mscorlib
namespace System.Globalization
class TimeSpanParse
internal static TimeSpan ParseExact(string input, string format, IFormatProvider formatProvider, TimeSpanStyles styles)
{
initobj(System.Globalization.TimeSpanParse/TimeSpanResult, ref timeSpanResult);
must be
TimeSpanResult timeSpanResult = new TimeSpanResult();
...
}

GenericMethod fail

input:
public static T GenericMethod(T t)
{
return t;
}

output:
public static T GenericMethod(T t)
{
return t;
}

Unnecessary base..ctor(); call

The decompiler creates an unnecessary even confusing base..ctor() call in the constructor.

Artificial code to show you, what I mean:

public MyClass()
{
    this.myField1 = true;
    base..ctor();
}

Lost method parameters

public override void add_busChanged(__RSControl_busChangedEventHandler) <---- handler1
{
bool flag;
try
{
Monitor.Enter(this, ref flag);
if (this.m_ConnectionPoint == null)
{
this.Init();
}
__RSControl_SinkHelper __RSControl_SinkHelper = new __RSControl_SinkHelper();
int i = 0;
this.m_ConnectionPoint.Advise((object)__RSControl_SinkHelper, ref i);
__RSControl_SinkHelper.m_dwCookie = i;
__RSControl_SinkHelper.m_busChangedDelegate = ; <----- handler1
this.m_aEventSinkHelpers.Add((object)__RSControl_SinkHelper);
}
finally
{
if (flag)
{
Monitor.Exit(this);
}
}
}

IL_0048: ldarg <---- 1

.NET 3.5 support

It takes several minor modifications to run ILSpy on .NET 3.5
Can we please add those with #if or something?


Majority of modifications are about generic collection covariance missing in .NET 3.5 -- basically sticking OfType<> now and then fixes it.

There are several string.Join calls with an absent signature. Select+ToArray does it.

There is a little Mono.Cecil patch to do with some obscure static type invocation. This one would just have to be ignored I guess.

And couple of WPF properties missing -- like layout rounding and text render preferences.

I've got the code and can post it.

redundant 'continue' in a foreach loop

this:

        foreach (string s in list)
        {
            s.ToLower();
        }

decompiled to this on debug build:

foreach (string current in list)
{
    current.ToLower();
    continue;
}

and to this on release build:

using (List.Enumerator<string> enumerator = list.GetEnumerator())
{
    while (enumerator.MoveNext())
    {
        enumerator.Current.ToLower();
        continue;
    }
}

"else" not needed after "throw new ArgumentNullException"

Hi,

I have noticed in a few places that an "else" is shown after argument checks (for nullity or anything else).

For example, in System.Collections.ArrayList :

public static ArrayList Adapter(IList list)
{
    if (list == null)
    {
        throw new ArgumentNullException("list");
    }
    else
    {
        return new ArrayList.IListWrapper(list);
    }
}

The else is not necessary.

System.Xaml.XamlXmlWriterException: Cannot write the given positional parameters because a matching constructor was not found.

Trying to decompile queryview.baml located in Profiler.Controls.dll causes this exception:

System.Xaml.XamlXmlWriterException: Cannot write the given positional parameters because a matching constructor was not found.
at System.Xaml.XamlXmlWriter.ExpandPositionalParameters.ExpandPositionalParametersIntoProperties(XamlXmlWriter writer)
at System.Xaml.XamlXmlWriter.ExpandPositionalParameters.WriteEndMember(XamlXmlWriter writer)
at System.Xaml.XamlXmlWriter.WriteEndMember()
at ICSharpCode.ILSpy.BamlDecompiler.DecompileBaml(MemoryStream bamlCode, Dictionary2 assemblies, String containingAssemblyFile) in d:\Projects\SharpDevelop\ILSpy\ILSpy\BamlDecompiler.cs:line 53 at ICSharpCode.ILSpy.BamlDecompiler.DecompileBaml(MemoryStream bamlCode, Dictionary2 assemblies, String containingAssemblyFile)
at ICSharpCode.ILSpy.TreeNodes.ResourceEntryNode.LoadBaml(AvalonEditTextOutput output) in d:\Projects\SharpDevelop\ILSpy\ILSpy\TreeNodes\ResourceEntryNode.cs:line 111
at ICSharpCode.ILSpy.TreeNodes.ResourceEntryNode.<>c__DisplayClass5.b__1() in d:\Projects\SharpDevelop\ILSpy\ILSpy\TreeNodes\ResourceEntryNode.cs:line 55

Crash wen update checking disabled

Steps to reproduce:

  1. disable update checking
  2. open about page
    FormatException raised (String was not recognized as valid DateTime).
    After this steps application crashed on start-up until clearing of c:\Users\user\AppData\Roaming\ISharpCode\ folder

foreach loops decompiled wrong

(this issue is just for reference, I know this is top priority :-)

The following 'foreach' loop:

        List<int> list = new List<int>();
        list.Add(1);
        list.Add(2);
        list.Add(3);
        list.Add(4);
        list.Add(5);

        foreach (int i in list)
        {
            DoSomething();
        }

decompiled to this:

List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);
List.Enumerator<int> enumerator = list.GetEnumerator();
try
{
    for (; ; )
    {
        flag = enumerator.MoveNext();
        if (!flag)
        {
            break;
        }
        else
        {
            current = enumerator.Current;
            this.DoSomething();
        }
    }
}
finally
{
    var arg_AF_0 = ref enumerator;
    constrained(System.Collections.Generic.List`1/Enumerator<System.Int32>);
    arg_AF_0.Dispose();
}

Unsafe code

This issue is just to help remind you of the current lack of support for unsafe code in ILSpy. A reasonable example of a fairly simple unsafe function is System.Double.IsInfinity.

Reflector gives the following code:
public static unsafe bool IsInfinity(double d)
{
return (((((long) &d)) & 0x7fffffffffffffffL) == 0x7ff0000000000000L);
}

ILSpy 1.0.0.427 Gives:
public static bool IsInfinity(double d)
{
return (ldind.i8((object)ref d) & 9223372036854775807L) == 9218868437227405312L;
}

There are a few things needed for this:

  • Unsafe blocks can be identified and be inserted into the code.
  • If the unsafe block covers a large enough percentage of the a function, it should be promoted to an "unsafe" keyword on the function itself.
  • The indirect loading instructions must be converted to pointer references.
  • Type inference needs to be improved to support inferring pointer types in expressions like those shown.

This particular function would also greatly benefit from an option or heuristics for displaying literals in Hexadecimal format, but that would be a separate issue.

stind.i4(hr, 0);

mscorlib
Microsoft.Win32.Win32Native.SetFilePointer()

should be

hr = 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.