From 75837925e964a487383aa67758519976b2943c32 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Sat, 10 Feb 2018 10:05:43 -0800
Subject: [PATCH] Find static descriptions inside data nodes

Right now this library only works if the static description is the entire data
node, but with upcoming LLD support everything will be in one data node. This
updates the logic for finding/parsing the program to search through the entire
data node and also know how big a program description is when it finds it.
---
 crates/wasm-bindgen-cli-support/src/lib.rs | 38 ++++++----------
 crates/wasm-bindgen-macro/src/ast.rs       | 52 +++++++++++++---------
 2 files changed, 44 insertions(+), 46 deletions(-)

diff --git a/crates/wasm-bindgen-cli-support/src/lib.rs b/crates/wasm-bindgen-cli-support/src/lib.rs
index a12b7d73..78fc2fed 100644
--- a/crates/wasm-bindgen-cli-support/src/lib.rs
+++ b/crates/wasm-bindgen-cli-support/src/lib.rs
@@ -134,31 +134,20 @@ fn extract_programs(module: &mut Module) -> Vec<shared::Program> {
         None => return ret,
     };
 
-    'outer:
-    for i in (0..data.entries().len()).rev() {
-        {
-            let mut value = bytes_to_u32(data.entries()[i].value());
-            loop {
-                match value.iter().position(|i| i.0 == (b'w' as u32)) {
-                    Some(i) => value = &value[i + 1..],
-                    None => continue 'outer,
-                }
-                match value.iter().position(|i| i.0 == (b'b' as u32)) {
-                    Some(i) => value = &value[i + 1..],
-                    None => continue 'outer,
-                }
-                match value.iter().position(|i| i.0 == (b'g' as u32)) {
-                    Some(i) => value = &value[i + 1..],
-                    None => continue 'outer,
-                }
-                match value.iter().position(|i| i.0 == (b':' as u32)) {
-                    Some(i) => value = &value[i + 1..],
-                    None => continue 'outer,
-                }
-                break
+    for entry in data.entries() {
+        let mut value = bytes_to_u32(entry.value());
+        loop {
+            match value.iter().position(|i| i.0 == 0x30d97887) {
+                Some(i) => value = &value[i + 1..],
+                None => break,
             }
-            // TODO: shouldn't take the rest of the value
-            let json = value.iter()
+            if value.get(0).map(|c| c.0) != Some(0xd4182f61) {
+                continue
+            }
+            let cnt = value[1].0 as usize;
+            let (a, b) = value[2..].split_at(cnt);
+            value = b;
+            let json = a.iter()
                 .map(|i| char::from_u32(i.0).unwrap())
                 .collect::<String>();
             let p = match serde_json::from_str(&json) {
@@ -169,7 +158,6 @@ fn extract_programs(module: &mut Module) -> Vec<shared::Program> {
             };
             ret.push(p);
         }
-        data.entries_mut().remove(i);
     }
     return ret
 }
diff --git a/crates/wasm-bindgen-macro/src/ast.rs b/crates/wasm-bindgen-macro/src/ast.rs
index ee6400a1..e0491f59 100644
--- a/crates/wasm-bindgen-macro/src/ast.rs
+++ b/crates/wasm-bindgen-macro/src/ast.rs
@@ -277,28 +277,38 @@ impl Program {
     }
 
     pub fn wbg_literal(&self, dst: &mut Tokens) -> usize {
-        let mut a = LiteralBuilder {
-            dst,
-            cnt: 0,
+        let mut tmp = Tokens::new();
+        let cnt = {
+            let mut a = LiteralBuilder {
+                dst: &mut tmp,
+                cnt: 0,
+            };
+            a.fields(&[
+                ("exports", &|a| a.list(&self.exports, Export::wbg_literal)),
+                ("imports", &|a| a.list(&self.imports, Import::wbg_literal)),
+                ("custom_type_names", &|a| {
+                    let names = self.exports.iter()
+                        .filter_map(|e| e.class)
+                        .collect::<BTreeSet<_>>();
+                    a.list(&names, |s, a| {
+                        let val = shared::name_to_descriptor(s.as_ref());
+                        a.fields(&[
+                            ("descriptor", &|a| a.char(val)),
+                            ("name", &|a| a.str(s.as_ref()))
+                        ]);
+                    })
+                }),
+            ]);
+            a.cnt
         };
-        a.append("wbg:");
-        a.fields(&[
-            ("exports", &|a| a.list(&self.exports, Export::wbg_literal)),
-            ("imports", &|a| a.list(&self.imports, Import::wbg_literal)),
-            ("custom_type_names", &|a| {
-                let names = self.exports.iter()
-                    .filter_map(|e| e.class)
-                    .collect::<BTreeSet<_>>();
-                a.list(&names, |s, a| {
-                    let val = shared::name_to_descriptor(s.as_ref());
-                    a.fields(&[
-                        ("descriptor", &|a| a.char(val)),
-                        ("name", &|a| a.str(s.as_ref()))
-                    ]);
-                })
-            }),
-        ]);
-        return a.cnt
+        let cnt = cnt as u32;
+        (quote! {
+            0x30d97887,
+            0xd4182f61,
+            #cnt,
+        }).to_tokens(dst);
+        tmp.to_tokens(dst);
+        (cnt as usize) + 3
     }
 }