アドベントペアプロ #8 denoland/deno

以下をhyper::Errorを使うようにしたかったけどいろいろ断念

io::Error::new(io::ErrorKind::Other, e)

https://docs.rs/hyper/0.11.17/hyper/error/enum.Error.html

エラーハンドリング https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/error-handling.html

なんだかんだ送ったプルリク

Rename source url to script name #1329 https://github.com/denoland/deno/pull/1329

Change default to false Base.bool #1330 https://github.com/denoland/deno/pull/1330

アドベントペアプロ #7 react-native

ファシリテータ: @ggtmtmgg セクリタリ: @ggtmtmgg 参加者: @saitoxu レポジトリ: https://github.com/facebook/react-native Issue: https://github.com/facebook/react-native/issues/20410

前回: https://hackmd.io/3bjDo5SDSvW9rnR-gKieow

spyOn

jestのspyOnが便利 spyOnをつかって、特定の関数が呼ばれるかをテストしたり、test中だけ実装を入れ替えたりできる。

...
    "flow": "flow",
    "flow-check-ios": "flow check",
    "flow-check-android": "flow check --flowconfig-name .flowconfig.android",
...

後でPR送る(@saitoxu)

React.

...
    // $FlowFixMe - TODO T29156721 `React.forwardRef` is not defined in Flow, yet.
    ViewToExport = React.forwardRef(View);
...

Reactv16.6.3では引数の型が定義されているので、おそらくコメントアウトごと消せば良い。 https://github.com/facebook/react/tree/v16.6.3

よくわからないので質問する https://github.com/facebook/react-native/issues/22595

アドベントペアプロ #9 expo/expo

home/ はexpoクライアント
ApolloClient はgraphQL用
home/ に狙いを定める

  • react-navigationのバージョンを上げる
  • console.log(e)をSentryに送る ← そもそもSenry入ってなかった
  • home/utils/requestCameraPermissionsAsync.jsのexportの仕方を治す

以下、home/ および、apps/以下のサンプルアプリの実行が出来ない問題

NixはThe Purely Functional Package Manager

クライアントアプリのビルド・セットアップ

$ curl https://nixos.org/nix/install | sh
$ . /Users/TSUBASA/.nix-profile/etc/profile.d/nix.sh
$ nix-env -iA nixpkgs.direnv
$ cd tools-public
$ yarn

iosのセットアップ

$ brew update
$ brew install git-lfs
$ cd expo/
$ git lfs pull
$ cd tools-pubilc
$ ./generate-files-ios.js
$ open ../ios/Exponent.xcworkspace

サブモジュールのインストール

$ git submodule init
$ git submodule update

もしくは

$ git clone --recurse-submodules git@github.com...

Permission denied (publickey).が出てしまったら

$ git clone --recurse-submodules https://github.com/expo/react-native.git

質問をする - フォーラムに投げる - apps/native-component-listとhome/を実行できない問題 - それぞれ同じエラーが出てるから同じ問題だと思う - それぞれの動かし方をまとめてるドキュメントがあれば教えて欲しい - もしくはこのエラーの対処法を...!

質問した https://forums.expo.io/t/running-apps-native-component-list-and-home-gets-duplicate-module-name-react-native-error/17047

アドベントペアプロ #6 denoland/deno

ファシリテータ: @ggtmtgg セクリタリ: @ggtmtmgg 参加者: @binaryta, @Haga

h2

src/fs.rs

// TODO: on posix, set mode flags to 0o700

サンプルコード

use std::fs;

fn main() -> std::io::Result<()> {
    let d = fs::create_dir("/Users/naritatakuya/dir")?;
    fs::set_permissions("/Users/naritatakuya/dir", perms);
    println!("{:?}", d); 
    Ok(())
}
-    // TODO: on posix, set mode flags to 0o700.
     let r = create_dir(buf.as_path());
+    let mut file;
+
     match r {
+      Ok(_) => {
+        file = OpenOptions::new().open(buf.as_path())?;
+      },
+      Err(e) => return Err(e),
+    }
+
+    let r = set_permissions(&mut file, 0o700);
+
+    match r {

このtestを通す

$ ./tools/test.py
use std::fs;
use std::fs::{OpenOptions};
use std::os::unix::fs::PermissionsExt;

fn main() -> std::io::Result<()> {
    // let d = fs::create_dir("/Users/TSUBASA/workspace/deno/foo")?;
    let file;
    let path = "/Users/TSUBASA/workspace/deno/foo";
    let r = fs::create_dir(path);

    match r {
      Ok(_) => {
        file = OpenOptions::new().create(true).open(path)?;
      },
      Err(e) => return Err(e),
    }

    let _r = file.set_permissions(PermissionsExt::from_mode(0o700 & 0o777));

    Ok(())
}

{ code: 22, kind: InvalidInput, message: "Invalid argument" } を出しているのをなおす`

use std::fs;
use std::fs::{OpenOptions};
use std::os::unix::fs::PermissionsExt;

fn main() -> std::io::Result<()> {
    // let d = fs::create_dir("/Users/TSUBASA/workspace/deno/foo")?;
    let file;
    let path = "/Users/TSUBASA/workspace/deno/foo";
    let r = fs::create_dir(path);

    match r {
      Ok(_) => {
        file = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(path)?;
      },
      Err(e) => return Err(e),
    }

    let _r = file.set_permissions(PermissionsExt::from_mode(0o700 & 0o777));

    Ok(())
}

Error: Os { code: 21, kind: Other, message: "Is a directory" } を出しているのをなおす

僕らは file のpermissionを変更するやつをdirにやろうとしてた。 dirのpermissionを変え無くてはならない。

use std::path::PathBuf;
use std::fs;
use std::os::unix::fs::PermissionsExt;

fn main() -> std::io::Result<()> {
    let path = PathBuf::from("/Users/naritatakuya/foo");
    let r = fs::create_dir(path.as_path());

    fs::set_permissions(path.as_path(), PermissionsExt::from_mode(0o700))?;
    Ok(())
}

が動いた

[Darwin (deno)] (master) $ find ./target/ -type f | grep msg_generated
./target//debug/gen/msg_generated.ts
./target//debug/gen/msg_generated.rs

アドベントペアプロ #5 denoland/deno

ファシリテーター: @ggtmtmgg
セクリタリ: @ggtmtmgg
参加者: @binaryta, @Haga

情報の共通化

unit_testsのエラーについて

$ ./tools/unit_tests.py target/debug/deno
...
HttpOther: an error occurred trying to connect: Connection refused (os error 61)

というエラーがでる問題と戦ってみた。

os error 61 が何か分からなかった。
サンドボックスのせいかな?--allow-netが上手く渡せてない?
もしくはlocalhost:4545をたてれてない?

replでconst, letが動かない問題について

replへの入力をreplLoop()が監視している
evaluate(code)で一行ずつ読み込む
evaluateのなかで呼んでるeval.call(window, code)に渡してるスコープが間違っていそう
cost window = globalEval("this");
globalEvalとevalがある。
単なるevalはそのスコープで動く。呼ばれたfunciton内のスコープで動く。
globalEvalはグローバルなスコープで動くっぽい

つまりreplの入力一行ごとに関数のブロックスコープが作られそのなかでconstで変数を定義してしまっている。

だから二行で書くと動かない、一行でやれば動く

> const a = 1;
undefined
> a
ReferenceError: a is not defined
> const a = 1; console.log(a);
1
undefined
> var c = 1; console.log(c);
1
undefined
> 

方針の決定

denoのts側のソースコードの問題に着手するというコンセプトで行く

Error("ErrTooLarge") を DenoError(TooLarge)に書き換える作業が良さそう

DenoErrorの使う

gen/以下からErrorKindをインポートしている。
genはたぶんGNでビルドされたやつ。
genはgRPCみたいに資源共有するやつが出力されてる。
msg.fbsが型共有の仕組みの実装部分。そこに記述してビルドすればgen/以下に出力されるはず。
なので、今回はmsg.fbにErrorKindにTooLargeを追加してビルドする。
その後、

new DenoError(
  ErrorKind.TooLarge,
  ""
)

に書き換える

エラーメッセージを考える

grow()はバッファの容量を増やす関数 今回のエラーはgrow()でこれ以上バッファを増やせないよってときに吐くエラー

      throw new DenoError(                                             
        ErrorKind.TooLarge,
        "The buffer can't grow because it becomes too large"           
      );

src/msg.fbs

enum ErrorKind: byte {
  // ...
  TooLarge,
}

テストがないのでテストを書く

やること

  • Bufferのwrite, readのどちらかもしくは両方で_grow()を使ってる部分を確認する
  • どれくらいの大きさでTooLargeになるのか把握する
  • TooLargeな状況で_grow()が呼ばれる状態をjs/buffer_test.tsで再現する
  • それをassertする
$ git remote add binaryta git@github.com:Tnarita0000/deno.git
$ git fetch binaryta js/modify-buffer-large-error
$ git checkout js/modify-buffer-large-error

c > MAXSIZE - c - nのときにTooLargeになる
cの実態に関して
c = this.capasitythis.capasity = this.buf.buffer.byteLength
this.bufはUint8Array型

nの実態に関して
write(p: Uint8Array)で渡される。
n = p.buffer.byteLength
書き込むデータの大きさ。

bufferTestGrow()がそのまま使えそう。

test(async function bufferTestGrow() {
  const tmp = new Uint8Array(72);
  for (let startLen of [0, 100, 1000, 10000, 100000]) {
    const xBytes = repeat("x", startLen);
    for (let growLen of [0, 100, 1000, 10000, 100000]) {
      const buf = new Buffer(xBytes.buffer as ArrayBuffer);
      // If we read, this affects buf.off, which is good to test.
      const { nread, eof } = await buf.read(tmp);
      buf.grow(growLen);
      const yBytes = repeat("y", growLen);
      await buf.write(yBytes);
      // Check that buffer has correct data.
      assertEqual(
        buf.bytes().subarray(0, startLen - nread),
        xBytes.subarray(nread)
      );
      assertEqual(
        buf.bytes().subarray(startLen - nread, startLen - nread + growLen),
        yBytes
      );
    }
  }
});

Number.MAX_VALUEをgrowLenに渡してみる。

$ deno
> 
1.7976931348623157e+308

こんな感じでtestを書いてみる

 
test(async function bufferTooLargeByteWrites() {
  init();
   const tmp = new Uint8Array(72);
  const growLen = Number.MAX_VALUE;
  const xBytes = repeat("x", 0);
  const buf = new Buffer(xBytes.buffer as ArrayBuffer);
  // If we read, this affects buf.off, which is good to test.
  const { nread, eof } = await buf.read(tmp);
   try {
    buf.grow(growLen);
  } catch (e) {
    assertEqual(stringify(e).split("\n")[0], "TooLarge: The buffer can't grow because it becomes too large");
  }
});

そしてPRを送って解散

https://github.com/denoland/deno/pull/1292

JS Ninja アドベントペアプロ #4 expo/expo

本記事は JS Ninja OSSペアプロ Advent Calendar 2018 - Qiitaの#4です。

ファシリテータ: @ggtmtmgg セクリタリ: @ggtmtmgg 参加者: @hmktsu

方針の整理

実務で使うためにレポジトリを良くする。そのためにPRを送る。

  • react-navigation v2 -> v3の変更でうまれた歪の回収
  • expoのpackageを作る
  • expoのいい感じのissueを見つける
  • expoのTODOコメントアウトを探す ←
$ git grep 'TODO' G apps
apps/native-component-list/screens/Contacts/ContactUtils.js:  // TODO: Evan: add support for calendars: https://github.com/moment/moment/issues/1454
apps/native-component-list/screens/MediaLibrary/MediaDetailsScreen.js:      case MediaLibrary.MediaType.video: // TODO: render Expo.Video component
apps/test-suite/tests/AdMobRewarded.js:          // TODO: Fix
apps/test-suite/tests/SQLite.js:// TODO: Only tests successful cases, needs to test error cases like bad database name etc.
packages/expo-firebase-app/tests/App.js:            // TODO add back in when android sdk support for deleting apps becomes available
apps/test-suite/tests/SQLite.js:// TODO: Only tests successful cases, needs to test error cases like bad database name etc.

↑これをがんばる

方針の整理

apps/test-suite/tests/SQLite.jsに失敗する場合のテストも追加してPRを投げる。 PRのメッセージで @ide さんにフィードバックを求める。

やることリスト

  • etcは無視してbad database nameな例のテストを書く
  • テストを実行する ←
  • PRを送る

test-suiteを実行するための手順

$ cd Desktop
$ git clone https://github.com/watanabeyu/expo expo
$ cd expo/apps/test-suite
~~$ yarn add --dev expo-yarn-workspaces~~
# 下記のfileから始まるパスのexpo-yarn-workspacesを使う
$ yarn
$ yarn test // ← エラーになりました

副産物PR

package.jsonのdevパッケージにexpo-yarn-workspacesを追加する

yarn add --dev expo-yarn-warkspacesだと、 Error: Cannot find module metro/src/blacklistになる

以下の追加の仕方が筋が良さそう

"devDependencies": {
  "expo-yarn-workspaces": "file:../../packages/expo-yarn-workspaces"
}

だと思ったけど、Error: Cannot find module 'metro-config/src/defaults/blacklist'になるところで断念。

参考議論

package.jsoncd Runnercd runnerにする

VSCodeの一部の環境ではcd Runnerでrunner/ディレクトリに移動できる。 他の環境ではRunner/ディレクトリが見つからないよエラーになってしまう。

PRを送ってマージされた。 https://github.com/expo/expo/pull/2929

アドベントペアプロ #3 deno

2018/12/05のアドベントペアプロの議事録 ファシリテータ: @binaryta
セクリタリ: @binaryta
参加者: @__syumai
レポジトリ: https://github.com/denoland/deno
issue: https://github.com/denoland/deno/issues/1159

denoのTODOコメントを見てみた

TS側一部抜粋

$ find ./js -type f -print | xargs grep TODO

.//net.ts:// TODO support other types:
.//net.ts:// TODO Support finding network from Addr, see https://golang.org/pkg/net/#Addr
.//net.ts: * TODO: `tcp4` (IPv4-only), `tcp6` (IPv6-only), `udp`, `udp4` (IPv4-only),

.//net_test.ts:/* TODO Fix broken test.
.//net_test.ts:/* TODO Fix broken test.
.//net_test.ts:/* TODO Fix broken test.
  • denoのinterfaceにはGoを流用しているものがいくつかある
  • net_testなどは、Go標準ライブラリのtestを読みつつ書いたら直せるかも

Rust側一部抜粋

$ find ./src -type f -print | xargs grep TODO

.//version.rs:// TODO Extract this version string from Cargo.toml.

実際に読んでみた

TS側

net_test.ts

コメントアウトを外しても普通にテスト既存のテストコードが動いたので問題無さそう.

net.ts

9  export type Network = "tcp";
10 // TODO support other types:
11 // export type Network = "tcp" | "tcp4" | "tcp6" | "unix" | "unixpacket";
12 
13 // TODO Support finding network from Addr, see https://golang.org/pkg/net/#Addr
14 export type Addr = string;
15 

プロトコルの種類を増やしてtypeを増やすTODO. 重そうだから一旦無視.

issue

Use let in REPL gives ReferenceError #1159

https://github.com/denoland/deno/issues/1159

  • REPLの実行時にletで定義した変数を後から参照したらReferenceErrorが発生する.
  • constも同様にReferenceErrorが発生する.
  • varで定義したものは動作しているように見えるが、実際にはグローバル変数(windowのプロパティ)になっているだけだった.

問題

  • evalはグローバルのスコープで実行されてしまう
const myEvalGen = () => {
  const lines = [];
  return line => {
    lines.push(line);
    const code = lines.join(";");
    try {
      return eval(code);
    } catch (err) {
      lines.pop();
      throw err;
    }
  };
};

const myEval = myEvalGen();
myEval("const a = 1;");
myEval("const b = 2;");
myEval("a + b;");
// => 3
myEval("a + b + c;");
// error thrown
myEval("const c = 3;");
myEval("a + b + c;");
// => 6 (error fixed)

解決策)

  1. 1行1行のソースコードlines配列にpushしていき、eval実行の行を毎度バッファする.
  2. 例外を一度でも吐くと、以降も例外が引き継がれてしまうでの、try/catchにより例外時の行はバッファから取り除く(popする)