node-ffi

C4ce16f549c450f4759eb37f5d5d1a63?s=47 othree
October 12, 2014

 node-ffi

C4ce16f549c450f4759eb37f5d5d1a63?s=128

othree

October 12, 2014
Tweet

Transcript

  1. node-ffi othree jsdc

  2. @othree othree.net MozTW F2E at HTC PhD Candidate

  3. Topics r3 ffi node-ffi node-ffi packages node-r3

  4. r3 ˖ 4VQFSGBTUSPVUFSMJCXSJUUFOJO$ ˖ CZDT https://github.com/c9s/r3

  5. r3 ˖ #BTFEPO%'" 焷㹁剤ꣳ朜䢀荈⹛堥  ˖ 1SFDPNQJMFSPVUFTJOUPQSFYUSFF ˖ UJNFTGBTUFSUIBO+PVSOFZ http://c9s.blogspot.tw/2014/05/r3-url-router-library.html

  6. How to Use libr3 ˖ $SFBUFUSFF ˖ *OTFSUSPVUFXJUIEBUB ˖ $PNQJMFUSFF

    ˖ .BUDISPVUFBOEHFUUIFEBUB
  7. Sample 1/2 n = r3_tree_create(10);! ! int route_data = 3;!

    ! r3_tree_insert_routel(n, METHOD_GET, "/blog/post", ! sizeof("/blog/post") - 1, &route_data );! ! int err = r3_tree_compile(n, &errstr);
  8. Sample 1/2 n = r3_tree_create(10);! ! int route_data = 3;!

    ! r3_tree_insert_routel(n, METHOD_GET, "/blog/post", ! sizeof("/blog/post") - 1, &route_data );! ! int err = r3_tree_compile(n, &errstr); Create Tree
  9. Sample 1/2 n = r3_tree_create(10);! ! int route_data = 3;!

    ! r3_tree_insert_routel(n, METHOD_GET, "/blog/post", ! sizeof("/blog/post") - 1, &route_data );! ! int err = r3_tree_compile(n, &errstr); Insert Route
  10. Sample 1/2 n = r3_tree_create(10);! ! int route_data = 3;!

    ! r3_tree_insert_routel(n, METHOD_GET, "/blog/post", ! sizeof("/blog/post") - 1, &route_data );! ! int err = r3_tree_compile(n, &errstr); Data
  11. Sample 1/2 n = r3_tree_create(10);! ! int route_data = 3;!

    ! r3_tree_insert_routel(n, METHOD_GET, "/blog/post", ! sizeof("/blog/post") - 1, &route_data );! ! int err = r3_tree_compile(n, &errstr); Compile
  12. None
  13. Sample 2/2 match_entry * entry = match_entry_create("/blog/post");! entry->request_method = METHOD_GET;!

    ! route *matched_route = r3_tree_match_route(n, entry);! matched_route->data; // The Data! ! match_entry_free(entry);! r3_tree_free(n);
  14. Sample 2/2 match_entry * entry = match_entry_create("/blog/post");! entry->request_method = METHOD_GET;!

    ! route *matched_route = r3_tree_match_route(n, entry);! matched_route->data; // The Data! ! match_entry_free(entry);! r3_tree_free(n); Create Entry
  15. Sample 2/2 match_entry * entry = match_entry_create("/blog/post");! entry->request_method = METHOD_GET;!

    ! route *matched_route = r3_tree_match_route(n, entry);! matched_route->data; // The Data! ! match_entry_free(entry);! r3_tree_free(n); Match Route
  16. Sample 2/2 match_entry * entry = match_entry_create("/blog/post");! entry->request_method = METHOD_GET;!

    ! route *matched_route = r3_tree_match_route(n, entry);! matched_route->data; // The Data! ! match_entry_free(entry);! r3_tree_free(n); Route Data
  17. match_entry ˖ 6TFEGPSDBQUVSFWBSJBCMFT ˖ "EENFUIPEDPOEJUJPO ˖ 'VUVSF ˖ *1NBTL ˖

    1PSUSBOHF
  18. Captures ˖ 6TF{variable_name}! ˖ $BOVTFSFHVMBSFYQSFTTJPO

  19. None
  20. Sample 2/2 match_entry * entry = match_entry_create(“/blog/post/1/2/3“);! entry->request_method = METHOD_GET;

    // Method Condition! ! route *matched_route = r3_tree_match_route(n, entry);! ! matched_route->data; // The Data! entry->vars; //Captured Vars, a string array! ! r3_tree_free(n);
  21. May I Use r3 in node

  22. Yes.

  23. How?

  24. How ˖ /PEFKTFYUFOTJPO ˖ 8SJUF$$ DBBTJOPEFS ˖ 'PSFJHO'VODUJPO*OUFSGBDF ''* 

    ˖ 6TFEZOBNJDMJC
  25. Why ˖ *UNJHIUGBTUFSUIBODVSSFOUTPMVUJPO ˖ 㔔捀䧮〳⟃#FDBVTF*DBO ˖ *BNXSJUJOHNZ1I%UIFTJT *BNXJMMJOHUPEP BOZUIJOHFYDFQUXSJUJOHUIFTJT

  26. Foreign Function Interface

  27. l "GPSFJHOGVODUJPOJOUFSGBDF ''* JT BNFDIBOJTNCZXIJDIBQSPHSBN XSJUUFOJOPOFQSPHSBNNJOH MBOHVBHFDBODBMMSPVUJOFTPSNBLF VTFPGTFSWJDFTXSJUUFOJOBOPUIFS https://en.wikipedia.org/wiki/Foreign_function_interface

  28. ˖ #ZVOEFSTUBOEDBMMJOHDPOWFOUJPO ˖ ,OPXIPXUPDBMMGPSFJHOGVODUJPOT TFOE BSHVNFOU BOESFBESFUVSOWBMVF ˖ *OBTTFNCMZMBOHVBHFMFWFM ˖

    $BMM$EZOBNJDMJCJONPTUDBTFT
  29. __cdecl val = sumExample(2,3) ; // push arguments to the

    stack, from right to left! push 3 ! push 2 ! ! ; // call the function! call _sumExample ! ! ; // cleanup the stack by adding the size of the arguments to! ; // ESP register! add esp,8 ! ! ; // copy the return value from EAX to a local variable (int c)! mov dword ptr [c],eax
  30. node-ffi

  31. l OPEFJTB/PEFKTBEEPOGPSMPBEJOH BOEDBMMJOHEZOBNJDMJCSBSJFTVTJOH QVSF+BWB4DSJQU*UDBOCFVTFEUP DSFBUFCJOEJOHTUPOBUJWFMJCSBSJFT XJUIPVUXSJUJOHBOZ$ DPEF https://github.com/node-ffi/node-ffi

  32. So node-ffi Knows ˖ )PXUPDBMMGVODUJPOJO$$ EZOBNJDMJC ˖ )PXUPDPOWFSU+BWB4DSJQUEBUBUP$$ EBUB ˖

    )PXUPTFOEQBSBNFUFS ˖ )PXUPHSBCSFUVSOWBMVF
  33. ˖ #Z!5PP5BMM/BUF

  34. @TooTallNate ˖ /BUIBO3BKMJDI ˖ /PEFKTDPSFDPNNJUUFS ˖ 0OFBVUIPSPG/PEFKTJO"DUJPO ˖ -PUTPGSFMBUFEQBDLBHF ˖

    /PE0CK$ /PEFKT̠0CKFDUJWF$CSJEHF
  35. ffi Packages ffi ref ref-struct ref-array

  36. ffi Foreign Function Call ref Reference Tools ref-struct Struct Helper

    ref-array Array Helper
  37. Example var ffi = require('ffi');! ! var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });! ! libm.ceil(1.5); // 2
  38. Example var ffi = require('ffi');! ! var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });! ! libm.ceil(1.5); // 2 Library name! Use dlopen
  39. Example var ffi = require('ffi');! ! var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });! ! libm.ceil(1.5); // 2 A function named ‘ceil’ return double
 Take one double parameter
  40. Example var ffi = require('ffi');! ! var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });! ! libm.ceil(1.5); // 2 return type
  41. Example var ffi = require('ffi');! ! var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });! ! libm.ceil(1.5); // 2 arguments type
  42. Types void bool byte pointer (u)short (u)int (u)int16 (u)int32 (u)int64

    (u)longlong size_t float (u)char string object
  43. Example var ffi = require('ffi');! ! var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });! ! libm.ceil(1.5); // 2 Call ceil
  44. To Use node-ffi ˖ 3FBEIFBEFSMF I  ˖ 8SJUFffi.LibraryEFOJUJPO ˖

    6TFJU
  45. math.h http://www.cplusplus.com/reference/cmath/ceil/ double ceil (double x); var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });
  46. math.h http://www.cplusplus.com/reference/cmath/ceil/ double ceil (double x); var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });
  47. math.h http://www.cplusplus.com/reference/cmath/ceil/ double ceil (double x); var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });
  48. math.h http://www.cplusplus.com/reference/cmath/ceil/ double ceil (double x); var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });
  49. r3.h

  50. None
  51. None
  52. Struct?

  53. Struct ˖ "TUSVDUJTBDUVBMMZBQPJOUFS ˖ 0LUPVTFQPJOUFS ˖ /PUPLUPVTFQPJOUFSJGXBOUUPMPBEJUTQSPQFSUZ ˖ 6TFSFGTUSVDU

  54. struct _edge {! char * pattern; // 8 bytes! node

    * child; // 8 bytes! unsigned char pattern_len; // 1 byte! unsigned char opcode:4; // 4 bit! unsigned char has_slug:1; // 1 bit! }; var StructType = require('ref-struct');! ! var edge = StructType({! pattern: "string",! child: "pointer",! pattern_len: "ushort",! opcode: "uchar",! has_slug: "uchar"! });
  55. ref-struct ˖ $SFBUF"#*DPNQMJBOUTUSVDUJOTUBODFTPOUPQPG #VFST ˖ "#* "QQMJDBUJPO#JOBSZ*OUFSGBDF  ˖ UIFTJ[FT

    MBZPVU BOEBMJHONFOUPGEBUBUZQFT ˖  https://en.wikipedia.org/wiki/Application_binary_interface
  56. https://mentorembedded.github.io/cxx-abi/abi.html

  57. https://mentorembedded.github.io/cxx-abi/

  58. Struct in Struct?

  59. typedef struct {! str_array * vars;! const char * path;

    // current path to dispatch! int path_len; // the length of the current path! int request_method; // current request method! void * data; // route ptr! char * host; // the request host! ! ...
  60. typedef struct {! str_array * vars;! const char * path;

    // current path to dispatch! int path_len; // the length of the current path! int request_method; // current request method! void * data; // route ptr! char * host; // the request host! ! ... var ref = require('ref');! ! var str_array = StructType({ ... });! ! var match_entry = StructType({! vars: ref.refType(str_array),! path: "string",! path_len: "int",! request_method: "int",! data: "pointer",! host: "pointer",! ...
  61. lSFGJTBOBUJWFBEEPOGPS/PEFKT UIBUBJETJOEPJOH$QSPHSBNNJOH JO+BWB4DSJQU CZFYUFOEJOHUIF CVJMUJO#VFSDMBTT https://tootallnate.github.io/ref/

  62. None
  63. ref.refType ˖ (FUSFGFSFODFUPEBUBUZQF

  64. l3FUVSOTBOFXDMPOFPGUIFHJWFO UZQFPCKFDU XJUIJUTJOEJSFDUJPO MFWFMJODSFNFOUFECZ https://tootallnate.github.io/ref/

  65. ref.refType ˖ (FUSFGFSFODFUPEBUBUZQF ˖ indirectionNFBOTUIFDPVOUPG*

  66. ref.refType StructType({! var1: str_array,! var2: ref.refType(str_array)! }); str_array var1;! str_array

    * var2;
  67. ref.refType StructType({! var1: str_array,! var2: ref.refType(str_array)! }); str_array var1;! str_array

    * var2;
  68. ref.refType StructType({! var1: str_array,! var2: ref.refType(str_array)! }); str_array var1;! str_array

    * var2;
  69. ref.refType StructType({! var1: str_array,! var2: ref.refType(str_array),! var3: ref.refType(ref.refType(str_array)),! }); str_array

    var1;! str_array * var2;! str_array **var3;
  70. Back to r3.h

  71. None
  72. None
  73. #define ˖ $QSFQSPDFTTPS ˖ 3FQMBDFUIFTUSJOHJOTPVSDFDPEFT ˖ 1SPDFTTCFGPSFDPNQJMF ˖ /PUSFBMGVODUJPO

  74. #define r3_tree_insert_path(n,p,d) r3_tree_insert_pathl_ex(n,p,s var libr3 = ffi.Library('libr3', {! "r3_tree_insert_pathl_ex": ["pointer",

    ["pointer", "string", " });! ! ! var r3_tree_insert_path = function (tree, path, data) {! return libr3.r3_tree_insert_pathl_ex(tree, path, path.length, };
  75. r3.h

  76. r3.h ˖  MJOFT ˖ TUSVDUT ˖  NFUIPET -PUTPGXPSL

  77. node-ffi-generate ˖ "VUPNBUJDHFOFSBUFEFOJUJPOGSPNIMF ˖ $POT ˖ 3FTVMUJTUPPEFUBJM UPPCJH ˖ .JHIUOPUTVJUGPSVTF

    ˖ EFOF https://github.com/tjfontaine/node-ffi-generate
  78. node-r3 ˖ 0OMZEFOFOFDFTTBSZNFUIPET ˖ NFUIPET ˖ 5SFFDSFBUF DPNQJMF EVNQ NBUDI

    GSFF ˖ *OTFSUSPVUF QBUI ˖ .BUDI@FOUSZDSFBUF GSFF
  79. Now We Can Write ffi.Library Define for r3

  80. 羳

  81. ㆭ剚鸏랃갫ⵄ

  82. ㉏겗 Route Data

  83. route * r3_tree_insert_routel(node *tree, int method,
 const char *path, int

    path_len, void *data);
  84. route * r3_tree_insert_routel(node *tree, int method,
 const char *path, int

    path_len, void *data);
  85. Route Data ˖ 3PVUFEBUBJTWPJEQPJOUFS ˖ $BOQPJOUUPBOZUZQFPGEBUB ˖ MJCSPOMZTUPSFUIFQPJOUFS

  86. Pointer?

  87. Pointer in JS ˖ 5IFSFJTOPSFBMQPJOUFSJO+BWB4DSJQU ˖ #VUZPVDBOVTF#VFS

  88. Buffer ˖ /PEFKTPOMZ ˖ #VFSJTBDIVOLPGNFNPSZJOTQFDJFEBEESFTT ˖ $BOCFUZQFMFTT TJ[FDBOCF ˖ OPEFEFBMQPJOUFSBTCVFS

  89. Example 1/2 var tree = libr3.r3_tree_create(10);! ! var data =

    new Buffer(data_str + '\u0000');! ! r3_tree_insert_route(tree, 'GET','/path', data);
  90. Example 2/2 var node = libr3.r3_tree_match_route(tree, entry);! ! var data

    = ref.deref(node).data; https://github.com/othree/node-r3/blob/46e29f72bbf68097ed66fd151f9ef42d5a3ede05/node-r3.js
  91. ref.deref ˖ %FSFGFSFODF ˖ (FUWBMVFGSPNCVFS ˖ *OUIJTDBTF EFSFGXJMMHFUBTUSVDU
 "OEJUTEBUBBUUSJCVUFJTXIBUXFXBOU

  92. The Data ˖ 5IFEBUBXFHPUJTBOPUIFSCVFSJOTUBODF ˖ 8FTFOEQPJOUFSPGUIJTCVFSUPSXIFOJOTFSU SPVUF ˖ 8FOFFEUPEFSFGFSFODFJUUPHFUSFBMEBUBWBMVF

  93. BUT

  94. The Problem ˖ %FSFGFSFODFdataXJMMHFUOPUIJOH ˖ #FDBVTFUIFTJ[FPGdataJTBOEUIFUZQFJT VOLOPXO

  95. Solution 1 ˖ 4FUEBUBUZQFBOETJ[F • buffer.type! • ref.reinterpret

  96. ref.reinterpret ˖ 3FTJ[FCVFS ˖ :PVOFFEUPLOPXUIFTJ[FPGZPVSEBUB

  97. Cons ˖ )BSEUPJNQMFNFOUWBSJPVTEBUBUZQF ˖ *GZPVEPJU NJHIUIVSUQFSGPSNBODF ˖ )BSEUPEFTJHO"1*

  98. Solution 2 ˖ "MXBZTVTFTUSJOH ˖ ref.readCString

  99. ref.readCString ˖ 3FBETUSJOHGSPNCVFS VOUJM00 ˖ /PUTUPQXIFONFFUCVFSFOE

  100. var data = new Buffer(data_str + '\u0000');

  101. var data = ref.readCString(ref.deref(node).data, 0);

  102. Cons ˖ 3PVUFEBUBJTMJNJUFEUPTUSJOHUZQF

  103. ˖ "GUFSTPMWFSTUJTTVF ˖ 8FIBWFSTUVTBCMFOPEFS ˖ #VUUIFQFSGPSNBODFJTWFSZCBE ˖ 4MPXFSUIBOEJSFDUPS

  104. ㉏겗 Performance

  105. Spec ˖ 6TFUIFTBNFUSFFJOSUFTUTCFODI ˖ 3VOPOJ.BD ˖ ()[*OUFM$PSFJ ˖ (#.)[%%3 https://github.com/c9s/r3/blob/master/tests/bench.c

  106. Route req/s director ~2200 node-r3 0.0.1 ~1900 'PSVOLOPXOSFBTPO
 *DBOOPUSFQSPEVDFUIJTOVNCFS

  107. What Takes Time ˖ %BUBUSBOTGPSN ˖ $BMMGPSFJHOGVODUJPO

  108. Transform String ˖ /FXCVFSGSPNHJWFOEBUBTUSJOH ˖ 3FBE$TUSJOHGSPNQPJOUFS

  109. data = new Buffer(data + '\u0000');! r3_tree_insert_path(this.tree, route, data); var

    node = r3_tree_match(this.tree, path, entry);! ! var data = ref.readCString(node.deref().data, 0);
  110. How to Skip Transform ˖ 4UPSFEBUBJO+BWB4DSJQUTJEF ˖ 6TFJOUFHFSJOEFYBTEBUB

  111. var i = this.i++;! this.data[i] = data;! ! var iref

    = ref.alloc('int', i);! ! libr3.r3_tree_insert_route(this.tree, method, route, iref); var node = libr3.r3_tree_match_route(this.tree, entry);! ! var index = node.deref().data.reinterpret(4).readUInt32LE(0);! ! var data = this.data[index];
  112. var i = this.i++;! this.data[i] = data;! ! var iref

    = ref.alloc('int', i);! ! libr3.r3_tree_insert_route(this.tree, method, route, iref); var node = libr3.r3_tree_match_route(this.tree, entry);! ! var index = node.deref().data.reinterpret(4).readUInt32LE(0);! ! var data = this.data[index]; Store Data
  113. ref.alloc ˖ $SFBUFCVFSCZHJWFUZQFTJ[FBOEWBMVF

  114. var i = this.i++;! this.data[i] = data;! ! var iref

    = ref.alloc('int', i);! ! libr3.r3_tree_insert_route(this.tree, method, route, iref); var node = libr3.r3_tree_match_route(this.tree, entry);! ! var index = node.deref().data.reinterpret(4).readUInt32LE(0);! ! var data = this.data[index]; Data for r3
  115. var i = this.i++;! this.data[i] = data;! ! var iref

    = ref.alloc('int', i);! ! libr3.r3_tree_insert_route(this.tree, method, route, iref); var node = libr3.r3_tree_match_route(this.tree, entry);! ! var index = node.deref().data.reinterpret(4).readUInt32LE(0);! ! var data = this.data[index]; Resize Buffer
  116. var i = this.i++;! this.data[i] = data;! ! var iref

    = ref.alloc('int', i);! ! libr3.r3_tree_insert_route(this.tree, method, route, iref); var node = libr3.r3_tree_match_route(this.tree, entry);! ! var index = node.deref().data.reinterpret(4).readUInt32LE(0);! ! var data = this.data[index]; Read Index
  117. readUInt32LE ˖ /PEFOBUJWFNFUIPE ˖ 3FBEVOTJHOFEJOUWBMVFGSPNCVFS

  118. Route req/s director ~2200 node-r3 0.0.1 ~1900 node-r3 0.0.3 ~5000

  119. More Pros ˖ /PNPSFMJNJUBUJPOPOEBUBUZQF ˖ "MM+4OBUJWFEBUBUZQFDBOCFVTF

  120. How About Foreign Calls ˖ 8IBUXFVTFE ˖ S@USFF@DSFBUF S@USFF@GSFF ˖

    S@USFF@JOTFSU@QBUI ˖ S@USFF@DPNQJMF ˖ NBUDI@FOUSZ@DSFBUF NBUDI@FOUSZ@GSFF ˖ S@USFF@NBUDI@SPVUF
  121. What is Omissible ˖ match_entry_create match_entry_free ˖ 0OMZSFRVJSFEXIFO ˖ 6TF)551NFUIPEDPOEJUJPO

    ˖ $BQUVSFBSHVNFOU
  122. So ˖ *DBOPNJUUIFTFNFUIPETXIFOOPUOFDFTTBSZ

  123. Route req/s director ~2200 node-r3 0.0.1 ~1900 node-r3 0.0.3 ~5000

    node-r3 0.1.0 7800~10600 Not Yet
  124. ˖ "GUFSTPMWFTFDPOEJTTVF ˖ 8FIBWFGBTUFSOPEFS ˖ #VUJUDBOOPUQBTTQSFTTVSFUFTU ˖ %BUBJOEFYCFDPNFTSBOEPNOVNCFS BOEDSBTI BGUFSNPSFSFRVFTU

  125. ㉏겗 Crash…

  126. None
  127. None
  128. Hard To Find The Bug

  129. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCase()];! if (!method) { throw new Error(route_frag[0]); }! r3_tree_insert_route(this.tree, method, route, data);! } else {! r3_tree_insert_route(this.tree, 0, route, data);! }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! };
  130. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; WBSJBCMFT
  131. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; DSFBUFUSFF
  132. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; EBUBTUPSBHF
  133. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; QBSTFSPVUFT
  134. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; DSFBUFJOEFY
  135. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; QBSTFTUSJOH
  136. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; NFUIPEDPOEJUJPO
  137. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; JOTFSUSPVUF
  138. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; DPNQJMFUSFF
  139. Any Idea?

  140. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCase()];! if (!method) { throw new Error(route_frag[0]); }! r3_tree_insert_route(this.tree, method, route, data);! } else {! r3_tree_insert_route(this.tree, 0, route, data);! }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! };
  141. The Bug ˖ dataJTMPDBMWBSJBCMF ˖ 8JMMCFGSFFEVSJOH(BSCBHF$PMMFDUJPO

  142. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! this.index = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! this.index[i] = data; // prevent GC! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCase()];! if (!method) { throw new Error(route_frag[0]); }! r3_tree_insert_route(this.tree, method, route, data);! } else {! r3_tree_insert_route(this.tree, 0, route, data);! }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! };
  143. 荈䊹涸隶侸荈䊹鎹 鎹䖤+BWB4DSJQU剤($

  144. ˖ "GUFSTPMWFBMMJTTVFT ˖ 8FOBMMZIBWFBSFBMMZTUBCMF IJHIQFSGPSNBODF SPVUFSMJC ˖ "OEUIBUTSFMFBTF ˖ /PXJT

  145. node-r3

  146. var Router = require('node-r3').Router;! ! var router = new Router({!

    "/foo": "data string",! "/foo/bar": function () {},! "/foo/bar/qoo": {obj: 1},! });! ! var dispatched = router.match("/foo");! ! router.free();
  147. var router = new Router({! "/": handler,! "/foo": fooHandler,! "/foo/{id}":

    fooHandler,! "POST /me": postMeHandler,! "GET /me": getMeHandler,! "POST|GET /post": postHandler,! });! ! var server = http.createServer(! router.httpHandler(notfound)! );
  148. Handler Function function (req, res, captures) array

  149. Error Handler Function function (req, res)

  150. Known Issues ˖ .FNPSZMFBL  ˖ 1FSGPSNBODFJNQSPWFNFOU

  151. Question?

  152. Thanks For your Attention