hylom'sWeblog

- hylom's blog
| about hylom / hylom.net | old contents | login

CentOS 7で「firewalld --permanent --change-interface」コマンドが動作しない問題の解決法

posted on 2016/07/12 19:57:27

 CentOS 7のfirewalldで特定のネットワークインターフェイスを特定のゾーンに関連付けるには、「firewall-cmd --zone=<ゾーン> --change-interface=<インターフェイス>」コマンドを使えとmanページに書いてある。このコマンド自体は正常に働くのだが、設定を永続的に保存するための「--permanent」オプションがうまく動かない。具体的には、firewalldを再起動すると設定が消えてしまう。

 実は、CentOSの元になっているRed Hatの「Bug Fix Advisory firewalld bug fix and enhancement update(2015年3月5日付け)を見ると、「The "--permanent --add-interface" option is supposed to be used only for interfaces that are not managed by the NetworkManager utility」と書いてある。つまり、nmtuiなどのツール経由で設定された、NetworkManager下で管理されているネットワークインターフェイスについては、--add-interfaceや--change-interfaceオプション利用時に--permanentオプションを指定しても効果が無いようだ。

 対処策としては、NetworkManager側でネットワークインターフェイスとゾーンの対応付けを行えば良い。ただし、nmtuiコマンドではゾーンの設定項目が無いため、nmcliコマンドでの設定が必要となる。

 まず、「nmcli c」コマンドで認識されているネットワークコネクションを確認する。

# nmcli c
名前                UUID                                  タイプ          デバイス
Wired connection 1  d2ee88e7-2e1c-4168-a1ad-8bd5b6ac4db3  802-3-ethernet  eth1
System eth0         5fb06bd0-0bb0-7ffb-45f1-d6edd65f3e03  802-3-ethernet  eth0

 ネットワークコネクションの詳細設定は「nmcli c show <コネクション名>」で確認できる。

# nmcli c show "Wired connection 1"
connection.id:                          Wired connection 1
connection.uuid:                        d2ee88e7-2e1c-4168-a1ad-8bd5b6ac4db3
connection.interface-name:              --
connection.type:                        802-3-ethernet
connection.autoconnect:                 yes
connection.autoconnect-priority:        0
connection.timestamp:                   1468320004
connection.read-only:                   no
connection.permissions:
connection.zone:                        --
connection.master:                      --
connection.slave-type:                  --
connection.autoconnect-slaves:          -1 (default)
connection.secondaries:
connection.gateway-ping-timeout:        0
connection.metered:                     不明
802-3-ethernet.port:                    --
802-3-ethernet.speed:                   0
802-3-ethernet.duplex:                  --
802-3-ethernet.auto-negotiate:          yes
802-3-ethernet.mac-address:             9C:A3:BA:28:8B:E2
802-3-ethernet.cloned-mac-address:      --
802-3-ethernet.mac-address-blacklist:
802-3-ethernet.mtu:                     自動
802-3-ethernet.s390-subchannels:
802-3-ethernet.s390-nettype:            --
802-3-ethernet.s390-options:
802-3-ethernet.wake-on-lan:             1 (default)
802-3-ethernet.wake-on-lan-password:    --
ipv4.method:                            manual
ipv4.dns:
ipv4.dns-search:
ipv4.addresses:                         192.168.1.10/24
ipv4.gateway:                           --
ipv4.routes:
ipv4.route-metric:                      -1
ipv4.ignore-auto-routes:                no
ipv4.ignore-auto-dns:                   no
ipv4.dhcp-client-id:                    --
ipv4.dhcp-send-hostname:                yes
ipv4.dhcp-hostname:                     --
ipv4.never-default:                     yes
ipv4.may-fail:                          yes
ipv6.method:                            auto
ipv6.dns:
ipv6.dns-search:
ipv6.addresses:
ipv6.gateway:                           --
ipv6.routes:
ipv6.route-metric:                      -1
ipv6.ignore-auto-routes:                no
ipv6.ignore-auto-dns:                   no
ipv6.never-default:                     no
ipv6.may-fail:                          yes
ipv6.ip6-privacy:                       -1 (不明)
ipv6.dhcp-send-hostname:                yes
ipv6.dhcp-hostname:                     --
GENERAL.名前:                           Wired connection 1
GENERAL.UUID:                           d2ee88e7-2e1c-4168-a1ad-8bd5b6ac4db3
GENERAL.デバイス:                       eth1
GENERAL.状態:                           アクティベート済み
GENERAL.デフォルト:                     いいえ
GENERAL.デフォルト6:                    いいえ
GENERAL.VPN:                            いいえ
GENERAL.ゾーン:                         --
GENERAL.DBUS パス:                      /org/freedesktop/NetworkManager/ActiveConnection/679
GENERAL.CON パス:                       /org/freedesktop/NetworkManager/Settings/1
GENERAL.スペックオブジェクト:           /
GENERAL.マスターパス:                   --
IP4.アドレス[1]:                        192.168.1.10/24
IP4.ゲートウェイ:
IP6.アドレス[1]:                        fe80::9ea3:baff:fe28:8be2/64
IP6.ゲートウェイ:

 ここで、「connection.zone」というのがゾーン設定になる。デフォルトではゾーンが指定されていないが、これを変更するには「nmcli c mod <コネクション名> <設定対象> <設定する値>」コマンドを実行する。たとえば、eth1を「internal」ゾーンに指定する場合は次のようになる

# nmcli c mod "Wired connection 1" connection.zone internal

 これでfirewalldを再起動すると、eth1がinternalゾーンに割り当てられるようになる。

# systemctl restart firewalld
# firewall-cmd --get-active-zones
internal
  interfaces: eth1
public
  interfaces: eth0

JenkinsでLet's encryptのSSL証明書を使う

posted on 2016/07/05 22:00:58

 Let's encryptで取得したSSL証明書をJenkinsで使おうとしてハマったので解決法のメモ。

 基本的にはhttps://issues.jenkins-ci.org/browse/JENKINS-22448に書いてあるとおり。まず、次のようなconvert.shを作る。

#!/bin/bash

HOST=<ホスト名>
KEY_PEM=/etc/letsencrypt/live/$HOST/privkey.pem
CERT_PEM=/etc/letsencrypt/live/$HOST/cert.pem
JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
KEYSTORE=/var/lib/jenkins/keystore

# convert ky
openssl rsa -des3 -in $KEY_PEM -out key.encrypted.pem
openssl pkcs12 -inkey key.encrypted.pem -in $CERT_PEM -export -out keys.encrypted.pkcs12
keytool -importkeystore -srckeystore keys.encrypted.pkcs12 -srcstoretype pkcs12 -destkeystore $KEYSTORE

 このconvert.shをroot権限で実行すると、/var/lib/jenkins/keystoreというファイルができる。ついでにカレントディレクトリにいくつかの中間ファイルができるが、それは削除してOK。

 次にJenkinsのサーバー設定ファイル(Ubuntuなら/etc/default/jenkins)内の「JENKINS_ARGS」付近を以下のように変更する。

HTTPS_KEYSTORE=/var/lib/jenkins/keystore
HTTPS_KEYSTORE_PASSWORD=<適当なパスワード>
HTTPS_PORT=8443
HTTPS_OPT="--httpsKeyStore=$HTTPS_KEYSTORE --httpsKeyStorePassword=$HTTPS_KEYSTORE_PASSWORD --httpsPort=$HTTPS_PORT"

JENKINS_ARGS="--webroot=/var/cache/$NAME/war --httpPort=$HTTP_PORT $HTTPS_OPT"

 これでJenkinsを再起動すればhttps://<ホスト名>:8443/での待ち受けが可能。鍵を更新したら毎回この作業が必要なので適当にcronで回すのがよさそう……なんだけど、途中でパスワードの入力を求められるのでそこら辺を自動化しないといけません。

ECMAScript 2015(ES6)でのクラス定義におけるclassキーワードとfunctionキーワードの違い

posted on 2016/06/07 00:58:08

 ECMAScript 2015では、新たにクラスを定義するためのclassキーワードが導入されている。MDNで提供されているドキュメントの「Classes」ページでは、「ECMAScript 6 で導入されたクラス構文は、既存のプロトタイプによるオブジェクト指向の糖衣構文です」と記述されている。しかし、厳密にチェックするとclassキーワードで定義したクラスとfunctionキーワードで定義したクラスは(実用上問題ないレベルで)挙動が微妙に異なる。その違いを検証してみよう。なお、検証に使用した環境はNode.js v6.2.1である。

$ node -v
v6.2.1

宣言方法の違い

 functionキーワードを使ってクラスを定義する場合、次のようにコンストラクタとしてクラス名を持つ関数を定義するのが一般的だ。

> function VectorFunction(x, y) {
... this.x = x;
... this.y = y;
... }
undefined

 いっぽうclassキーワードを利用する場合、次のようにconstructor関数を使ってクラスのコンストラクタを定義する。

> class VectorClass {
... constructor(x, y) {
..... this.x = x;
..... this.y = y;
..... }
... }
[Function: VectorClass]

 classキーワードを利用した場合でも、作成されるのはあくまでFunctionオブジェクト(=関数)である。

newキーワードなしで実行した際の挙動の違い

 これらのクラスのインスタンスを作成するには、この関数をnewキーワード付きで実行する。

> v1 = new VectorFunction(3, 4)
VectorFunction { x: 3, y: 4 }
> v2 = new VectorClass(3, 4)
VectorClass { x: 3, y: 4 }

 この挙動はどちらの場合も同じだ。しかし、newキーワード無しでクラスを関数として実行した場合、functionキーワードを使って定義したクラスとclassキーワードを使って定義したクラスは挙動が異なる。

 functionキーワードを使って定義したクラスは、newキーワード無しで関数として実行すると意図しない結果を生み出すことがある。なぜなら、newキーワード無しで関数を実行した場合、this変数にglobalオブジェクト(strict modeの場合はundefined)が渡されるからだ。

 たとえば今回のケースでは、非strict modeの場合グローバルオブジェクトのプロパティが勝手に変更されてしまう。

> x = 0
0
> y = 0
0
> v1 = VectorFunction(3, 4)
undefined
> x
3
> y
4

 いっぽう、classキーワードで定義したクラスはそのまま実行することはできず、TypeErrorが発生する。

> v2 = VectorClass(3, 4)
TypeError: Class constructor VectorClass cannot be invoked without 'new'
    at repl:1:6
    at REPLServer.defaultEval (repl.js:272:27)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.<anonymous> (repl.js:441:10)
    at emitOne (events.js:101:20)
    at REPLServer.emit (events.js:188:7)
    at REPLServer.Interface._onLine (readline.js:224:10)
    at REPLServer.Interface._line (readline.js:566:8)
    at REPLServer.Interface._ttyWrite (readline.js:843:14)

 ECMA-262の「14.5.14 Runtime Semantics: ClassDefinitionEvaluation」および「9.2.9 MakeClassConstructor(F)」で説明されているが、classキーワードでクラスを定義した場合、生成されたFunctionオブジェクトの「FunctionKind」内部スロットに「classConstructor」という値がセットされる。この内部スロットはFunctionオブジェクトの種別を格納するもので、「normal」および「classConstructor」、「generator」のいずれかを持つ(「9.2 ECMAScript Function Objects」)。FunctionKind内部スロットの値がclassConstructorの場合、関数を実行する際に実行される「Call」内部メソッドの実行時にTypeError例外が送出される(「9.2.1 [[Call]] ( thisArgument, argumentsList)」)。なお、FunctionKind内部スロットの値がclassConstructorになるのは、classキーワードでクラスを定義した場合のみである。

所有するプロパティの違い

 classキーワードで定義したクラスは、functionキーワードで定義したクラスと異なり「caller」および「arguments」プロパティを持たない。

> Object.getOwnPropertyNames(VectorFunction)
[ 'length', 'name', 'arguments', 'caller', 'prototype' ]
> Object.getOwnPropertyNames(VectorClass)
[ 'length', 'name', 'prototype' ]

 また、classキーワードで定義したクラスのprototypeプロパティはwritableではないが、functionキーワードで定義したクラスのprototypeプロパティはwritableである。

> Object.getOwnPropertyDescriptor(VectorFunction, "prototype")
{ value: VectorFunction {},
  writable: true,
  enumerable: false,
  configurable: false }
> Object.getOwnPropertyDescriptor(VectorClass, "prototype")
{ value: VectorClass {},
  writable: false,
  enumerable: false,
  configurable: false }

 もちろん、どちらの場合もprototypeオブジェクトにプロパティ/メソッドを追加することは可能だ。

> VectorFunction.prototype.norm = function () {
... return Math.sqrt(this.x * this.x + this.y * this.y);
... }
[Function]
> VectorClass.prototype.norm = function () {
... return Math.sqrt(this.x * this.x + this.y * this.y);
... }
[Function]

 このようにして定義したメソッドは、どちらも同じように実行することが可能だ。

> v1 = new VectorFunction(3, 4)
VectorFunction { x: 3, y: 4 }
> v1.norm()
5
> v2 = new VectorClass(3, 4)
VectorClass { x: 3, y: 4 }
> v2.norm()
5

functionキーワードを使ったクラス宣言でしかできないこと

 classキーワードを使ってクラスを宣言すると、そのクラス自体を関数として実行することができなくなる。多くの場合でこのこと自体にデメリットはないが、意図的に(newキーワードなしに)クラスを関数として実行したいというケースも考えられる。たとえば次の例は、strict modeではnewキーワード無しにクラスを関数として実行した場合にthis変数がundefinedになることを利用し、newキーワード付きで実行した場合とnewキーワード無しで実行した場合とで異なる処理を行わせるものだ。

$ node --use_strict
> function Vector(x, y) {
... if (this === undefined) {
..... return new Vector(x, y);
..... }
... this.x = x;
... this.y = y;
... }
undefined
> Vector(3, 4)
Vector { x: 3, y: 4 }
> new Vector(3, 4)
Vector { x: 3, y: 4 }

 このようにして定義したVectorクラスは、newキーワードがあっても無くとも同様にVectorクラスのインスタンスを返す。

ECMAScript 2015の仕様書を読む(その22)

posted on 2016/06/01 01:27:24

 ECMAScript 2015の仕様書(ECMA-262)を読んでいます。今回は付録について(付録A、D、Eについては詳細な内容は割愛)。

付録A

 文法まとめ。本編で説明されている文法がここでまとめられている。とりあえずここを見れば記述可能な文法が分かる。

付録B

 Webブラウザ向けの追加機能について。本来推奨されないが、Webブラウザ上で実行されるコードの互換性を保つために規定されているもので、Webブラウザ以外のECMAScript実行環境では実装しなくてもよい。また、これらはstrict modeでは利用できない。

 規定されているのは下記。

  • 数値リテラルにおける0で始まる8進数表記(本来であれば8進数表記は0Oで始まる必要がある)
  • 8進数表記を使ったエスケープシーケンス(バックスラッシュに続けて[0-8]もしくは[0-3][0-8]、[0-4][0-8]、[0-3][0-8][0-8])
  • HTML風コメント(<!--、-->を利用するもの)
  • Unicodeの基本多言語面(BMP)に関連する正規表現パターン
  • グローバルオブジェクトのescape(string)およびunescape(string)プロパティ
  • Object.prototype.__proto__
  • String.prototype.substr(start, length)
  • String.prototypeのanchor、big、blink、bold、fixed、fontcolor、fontsize、italics、link、small、strike、sub、supメソッド
  • Date.prototypeのgetYear、setYear、toGMTStringメソッド
  • RegExp.prototypeのcompileメソッド
  • オブジェクトの初期化時における__proto__プロパティの利用
  • ラベルを使った関数定義
  • ブロックレベルでの関数定義
  • ifステートメント内での関数定義
  • catchブロック内での重複した変数定義

 なお、escapeプロパティは[A-Za-z0-9@*_+-./]をURLエンコードする。

付録C

 ECMAScriptにおけるstrict modeについて。strict modeでは非strct modeと下記が異なる。

  • 予約語にimplements、interface、let、private、protected、public、static、yieldが追加されている
  • 付録Cで定義されているWebブラウザ向けの互換性維持のための文法や機能が利用できない
  • 宣言されていない識別子や参照先が存在しないリファレンスがグローバルオブジェクトのプロパティとして生成されない
  • 各種構文でeval、argumentsを左手側に置くことはできない
  • 関数内で引数が格納されるオブジェクト(argumentsオブジェクト)のcallerやcalleeプロパティ
  • argumentsオブジェクトに格納されている値と引数として渡される値は別
  • argumentsオブジェクトは変更不可
  • 「識別子 eval」や「識別子 arguments」はSyntaxErrorとなる
  • eval内ではそれを呼び出した環境の変数や関数のインスタンスを生成できない
  • thisの値がnullやundefinedだった場合、これらがグローバルオブジェクトに置き換えられることはく、またプリミティブ値が対応するラッパーオブジェクトに変換されることはない
  • 値や関数引数、関数名に対するdelete演算子の利用がSyntaxErrorに
  • Configurableでないプロパティに対するdelete演算子の利用がSyntaxErrorに
  • with文は利用できない
  • try〜catch文でcatchを構成する識別子がevalやargumentsだった場合、SyntaxErrorに
  • 関数定義の歳の引数パラメータで同じものを2つ以上使うとSyntaxErrorに
  • 関数のcallerやargumentsプロパティについてこの仕様書で規定されている以外の拡張をすべきではない

付録D

 過去のバージョンのECMAScriptから挙動が修正された点について。

付録E

 過去のバージョンのECMAScriptとは互換性のない変更について。

ECMAScript 2015の仕様書を読む(その21)

posted on 2016/05/31 00:26:16

 ECMAScript 2015の仕様書(ECMA-262)を読んでいます。今回はリフレクションやプロキシ、モジュール名前空間に関連するオブジェクトに関する第26章。

第26章第1節

 Reflectオブジェクトについて。Reflectオブジェクトは内部オブジェクトとして定義されているオブジェクトで、グローバルオブジェクトのReflectプロパティの初期値になっている。関数オブジェクトではないので直接このオブジェクトを実行することはできないし、newキーワードを使って直接コンストラクタを呼び出すこともできない。

 Reflectオブジェクトは以下のプロパティ/メソッドを持つ。これらはObjectと同名のものもあるが、targetがオブジェクトでない場合必ずTypeErrorを発生させる点が異なる。

Reflect.apply(target, thisArgument, argumentsList)	target関数をargumentsListを引数として与えて実行する。このときthisにはthisArgumentが渡される
Reflect.construct(target, argumentsList [, newTarget])	targetを元に新たにオブジェクトを作成する。このときargumentsListを引数としてコンストラクタが実行される。newTargetがあ場合、これをコンストラクタとして使う。
Reflect.defineProperty(target, propertyKey, attributes)	targetにpropertyKeyという名前でプロパティを追加し、値にattributesをセットする
Reflect.deleteProperty(target, propertyKey)	targetのproprtyKeyプロパティを削除する
Reflect.enumerate(target)	targetのenumerableなプロパティに帯するiteratorを返す
Reflect.get(target, proertyKey [, receiver])	tagetのpropertyKeyプロパティを取得する。receiverが指定された場合、これをthisとして使用する
Reflect.getOwnPropertyDescriptor(target, propertyKey)	targetのpropertyKeyのPropertyDescriptorを返す
Reflect.getPrototypeOf(target)	targetのprototypeを返す
Reflect.has(target, propertyKey)	targetがpropertyKeyプロパティを持っていたらtrueを返す
Reflect.isExtensible(target)	targetがextensibleならtrue
Reflect.ownKeys(target)	targetが独自に持つプロパティキーの配列を返す
Reflect.preventExtensions(target)	targetの拡張を禁止する
Reflect.set(target, propertyKey, V [, receiver])	targetのpropertyKeyプロパティにVをセットする。receiverが与えられた場合、これをthisとする。
Reflect.setPrototypeOf(target, proto)	targetのプロトタイプをprotoに設定する

第26章第2節

 Proxyオブジェクトについて。Proxyオブジェクトは、あるオブジェクトについて、これを変更することなくそのプロパティやメソッドに対する挙動を追加・変更するために使われるオブジェクトである。

 ProxyオブジェクトはグローバルオブジェクトのProxyプロパティの初期値。Proxyコンストラクタは(target, handler)という引数を取り、targetをベースとした新たなproxyオブジェクトを作成する。このオブジェクトのプロパティにアクセスしたり、メソッドを実行しようとするとhandler関数が実行される。なおProxyオブジェクトは通常の関数としての実行は不可で、newキーワード無しで実行するとTypeErrorとなる。

 また、ProxyオブジェクトはProxy.revocable(target, handler)というメソッドを持つ。このメソッドは取り消し可能な(proxyを無効にできる)proxyオブジェクトを返す。このオブジェクトはproxy自体を格納するproxyプロパティおよびproxyを無効にするrevokeメソッドを持つ。

第26章第3節

 モジュール名前空間オブジェクト(Module Namespace Object)について。このオブジェクトはimportキーワードを使ってモジュールをロードした際に生成される。@@toStringTagプロパティおよび[@@iterator]()メソッドを持ち、前者は"Module"を返す。後者はモジュールの名前空間に登録されているキーに対するiteratorを返す。

ECMAScript 2015の仕様書を読む(その20)

posted on 2016/05/26 23:40:32

 ECMAScript 2015の仕様書(ECMA-262)を読んでいます。今回はイテレータやジェネレータ、Promise関連のオブジェクトに関する第25章。

第25章1節

 イテレーションについて。iterate可能なオブジェクトは、@@iteratorプロパティでそのオブジェクトに対応するiteratorを取得できる。iteratorはnextメソッドを持ち、このメソッドを実行するとIteratorResultオブジェクトを返す。このオブジェクトは次のメソッドを持つ。これらはすべてIteratorResultオブジェクトを返す。

next

 また、オプションで次のプロパティを持つ。これらはすべてIteratorResultオブジェクトを返す。

return
throw

 returnは、それ以上nextメソッドを呼び出さないことをiteratorに通知する際に実行される。また、throwはiteratorに何らかのエラーが発生したことを通知するために使われる。throwは引数にexceptionオブジェクトなどのエラー内容を格納するオブジェクトを与えることができる。

 IteratorResultオブジェクトは次のプロパティを持つ。

done	iterateが完了するとtrue
value	対応する値を格納する

第25章2節

 GeneratorFunctionについて。GeneratorFunctionはFunctionオブジェクトの派生オブジェクトであり、Functionオブジェクトのコンストラクタから派生した独自のコンストラクタと、Iteratorのプロトタイプから派生した独自のprototypeを持つ。GeneratorFunctionはグローバルオブジェクトではないが、下記のコードを用いて取得できる。

Object.getPrototypeOf(function*(){}).constructor

 GeneratorFunctionは関数として実行できる。newキーワードを付けても付けなくても同じ挙動を行う。サブクラス化も可能だが、その際はコンストラクタ内でsuperキーワードを使ってGeneratorFunctionオブジェクトを生成する必要がある。また、GeneratorFunctionオブジェクトはfunction*キーワードで生成できる。

 GeneratorFunctionは次のような形式で実行できる。

GeneratorFunction(p1, p2, ..., pn, body)

 bodyは実行コード、p1〜pnはそれに与える引数の識別子である。これらは通常は文字列として与えられる。

GeneratorFunction.prototype.constructor	内部オブジェクト
GeneratorFunction.prototype.prototype	内部オブジェクト
GeneratorFunction.prototype[@@toStringTag]	"GeneratorFunction"

 また、GeneratorFunctionインスタンスはlengthおよびname、prototypeプロパティを持つ。

第25章3節

 ジェネレータオブジェクトについて。このオブジェクトはジェネレータ関数のインスタンスであり、IteratorとIterableインターフェイスの両方の性質を持つ。このオブジェクトはジェネレータオブジェクトのprototypeではなく、インスタンスを作成したジェネレータ関数のprototypeを引き継ぐ。つまり、GeneratorオブジェクトのprototypeオブジェクトはGeneratorFunction.prototypeである。

 Generator.prototypeは次のプロパティ/メソッドを持つ。

Generator.prototype.constructor コンストラクタ
Generator.prototype.next(value)	ジェネレータ関数の状態をvalueにする
Generator.prototype.return(value)	valueを返して処理を終了させる
Generator.prototype.throw(exception)	ジェネレータ関数で例外を発生させる
Generator.prototype[@@toStringTag]	"Generator"

 ジェネレータ関数内では、yieldキーワードの戻り値を使っているケースがある。この場合、次にジェネレータ関数が呼び出された場合にその戻り値が関数内で続く処理に渡されるわけだが、nextメソッドを利用することでその値を変更できる。

第25章4節

 Promiseオブジェクトについて。Promiseオブジェクトは遅延・非同期処理を行うためのオブジェクト。内部的に「Resolve」と「Reject」の2つの関数オブジェクトを保持し、またfulfilled、rejected、pendingの3つのステータスのどれか1つを持つ。

 内部で非同期処理を行っている場合など、それが終了する時点では結果が分からない関数でPromiseオブジェクトを返り値として使用することが想定されている。このオブジェクトは処理が完了するとfulfilledもしくはrejectedのステータスとなり、ステータスを監視することで並列処理が完了したのか、またその結果がどうなったのかを知ることができる。

 Promiseオブジェクトは関数としては実行できない。newキーワード付きでコンストラクタとしての実行のみが許可される。Promiseオブジェクトのコンストラクタはサブクラス化可能であるが、その場合はsuperキーワードを使ってコンストラクタ内でPromiseオブジェクトを生成する必要がある。

 PromiseのコンストラクタはPromise(executor)という形で呼び出される。executorは関数オブジェクトであり、遅延・非同期処理が完了した際に呼び出される。また、resolveとrejectという2つの引数を持つ。いずれも関数オブジェクトで、executor関数内で処理が成功したのか、それとも失敗したのかを通知するために呼び出すことができる。また、executor関数の終了(returnの実行)は遅延・非同期処理の完了を意味するのでは無く、その処理が受け付けられたというのを示すだけである。

 引数として与えられるresolve関数は、1つの引数を取る。executor関数内で対応するPromiseオブジェクトの解決を行いたい際にこの関数が呼び出され、引数には遅延・非同期処理が進められる際に得られた値が渡される。

 引数として与えられるreject関数も1つの引数を取る。executor関数内で対応するPromiseオブジェクトがrejectされ、成功しないことが分かった際にこの関数が呼び出される。引数にはrejectされたことを示す値(一般的にはErrorオブジェクト)が渡される。

 Promiseオブジェクトは次のメソッド/プロパティを持つ。

Promise.all(iterable)	与えられたPromiseのすべてが成功した際に成功となる新たなPromiseオブジェクトを返す
Promise.prototype	内部オブジェクト
Promise.race(iterable)	与えられたPromiseのうち、最初に完了したPromiseと同じ結果を返す新たなPromiseオブジェクトを返す
Promise.reject(r)	与えられた引数によって失敗状態となる新たなPromiseオブジェクトを返す
Promise.resolve(x)	与えられた引数によって成功状態となる新たなPromiseオブジェクトを返す
Promise[@@species]	getter

 また、Promise.prototypeは下記のメソッド/プロパティを持つ。

Promise.prototype.catch(onRejected)	Promiseが失敗したときに実行されるコールバック関数を設定する
Promise.prototype.constructor	コンストラクタ
Promise.then(onFulfilled, onRejected)	成功した際および失敗した際に実行されるコールバック関数を設定する
Promise.prototype[@@toStringTag]	"Promise"

ECMAScript 2015の仕様書を読む(その19)

posted on 2016/05/23 22:01:25

 ECMAScript 2015の仕様書(ECMA-262)を読んでいます。今回はArrayBufferおよびDataView、JSONオブジェクトについて規定する第24章。

第24章1節

 ArrayBufferオブジェクトについて。ArrayBufferは、処理系内部に確保された、任意の値を格納できるメモリバッファをラップするオブジェクトとなる。このオブジェクトは内部的にはデータを格納するメモリバッファと、そのバッファの長さを保持する。

 ArrayBufferコンストラクタはサブクラス化可能にデザインされている。その場合、サブクラスのコンストラクタ内ではsuperキーワードを使ってWeakMapコンストラクタを呼び出してインスタンスの初期化を行う必要がある。

 ArrayBufferをnewキーワード付きで関数として実行すると、ArrayBufferのインスタンスを生成できる。この際、引数にはバッファの長さを指定できる。newキーワード無しで実行するとTypeErrorとなる。

 ArrayBufferオブジェクトは下記のメソッド/プロパティを持つ。

ArrayBuffer.isView(arg)	argがViewedArrayBufferであればtrueを返す
ArrayBuffer.prototype	内部オブジェクト
ArrayBuffer[@@species]	getter。

 また、ArrayBuffer.prototypeは次のメソッド/プロパティを持つ。

ArrayBuffer.prototype.byteLength	getter。対応するバッファのバイト数を返す
ArrayBuffer.prototype.constructor	コンストラクタ
ArrayBuffer.prototype.slice(start, end)	対応するバッファのstartバイトからendバイトを新たに作成したArrayBufferにコピーして返す
ArrayBuffer.prototype[@@toStringTag]	"ArrayBuffer"

第24章2節

 DataViewオブジェクトについて。DataViewオブジェクトは対応するArrayBufferに格納されたデータにアクセスするためのメソッドを提供する。データへのアクセスはすべてNumber形式で行い、またコンストラクタで指定したbyteOffsetおよびbyteLengthの範囲を超える範囲へはアクセスできない。 

 ArrayBufferコンストラクタはサブクラス化可能にデザインされている。その場合、サブクラスのコンストラクタ内ではsuperキーワードを使ってWeakMapコンストラクタを呼び出してインスタンスの初期化を行う必要がある。

 DataViewオブジェクトをnewキーワード付きで関数として実行すると、DataViewオブジェクトのインスタンスを生成できる。引数はDataView(buffer [, byteOffset [, byteLength]])の最大3つ。bufferは対応付けるArrayBuffer(もしくはその派生オブジェクト)。byteOffset、ByteLengthはそれぞれバッファを参照する際のオフセットと、最大長さ。

 DataViewオブジェクトはprototypeプロパティのみを持つ。また、DataView.prototypeは次のメソッド/プロパティを持つ。

DataView.prototype.buffer	getter。対応付けられたArrayBufferを返す
DataView.prototype.byteLength	getter。参照できる最大バイト数を返す
DataView.prototype.byteOffset	getter。バッファを参照する際のオフセットを返す
DataView.prototype.constructor	コンストラクタ
DataView.prototype.getFloat32(byteOffset [, littleEndian])	対応付けられたバッファのbyteOffsetバイト目からのデータをFloat32として扱い、それをNumber形式に変換してデータを取り出す。littleEndianがtrueならリトルエンディアン、falseならビッグエンディアンで取り出す。以下、取り出す形式が異なるのみで同じ処理を行う
DataView.prototype.getFloat64(byteOffset [, littleEndian])	
DataView.prototype.getInt8(byteOffset)	
DataView.prototype.getInt16(byteOffset [, littleEndian])	
DataView.prototype.getInt32(byteOffset [, littleEndian])	
DataView.prototype.getUint8(byteOffset)	
DataView.prototype.getUint16(byteOffset [, littleEndian])	
DataView.prototype.getUint32(byteOffset [, littleEndian])	
DataView.prototype.setFloat32(byteOffset, value [, littleEndian])	対応付けられたバッファのbyteOffsetバイト目以降に、valueをFloat32として扱ってバイナリ化したものを書き込む。littleEndianがtrueならリトルエンディアン、falseならビッグエンディアンで取り出す。以下、取り出す形式が異なるのみで同じ処理を行う
DataView.prototype.setFloat64(byteOffset, value [, littleEndian])	
DataView.prototype.setInt8(byteOffset, value)	
DataView.prototype.setInt16(byteOffset, value [, littleEndian])	
DataView.prototype.setInt32(byteOffset, value [, littleEndian])	
DataView.prototype.setUint8(byteOffset, value)	
DataView.prototype.setUint16(byteOffset, value [, littleEndian])	
DataView.prototype.setUint32(byteOffset, value [, littleEndian])	
DataView.prototype[@@toStringTag]	"DataView"

第24章3節

 JSONオブジェクトについて。JSON形式で記述されたテキストベースのデータをオブジェクト化するもの。

 JSONオブジェクトはコンストラクタを持たないため、newキーワード付きでは実行できず、また関数として実行することもできない。

 JSONオブジェクトは次のメソッドを持つ。

JSON.parse(text [, reviver])	textをJSON文字列としてパースしECMAScriptオブジェクト/値を生成する。関数オブジェクトであるreviverが与えられた場合、この関数に対しthisとしてプロパティを含むオブジェクトを、引数にプロパティ名と値を与えて実行してこの値を変換できる
JSON.stringify(value, [, replacer [, space]])	valueをJSON文字列に変換する。関数オブジェクトであるreplacerが与えられた場合、引数にプロパティ名と値を与えて実行してその値を変換できる。spaceがtrueだった場合、変換結果を整形する。
JSON[@@toStringTag]	"JSON"

ECMAScript 2015の仕様書を読む(その18)

posted on 2016/05/19 02:14:55

 ECMAScript 2015の仕様書(ECMA-262)を読んでいます。今回はWeakMapについて規定する第23章第3節とWeakSetについて規定する第4節。

第23章3節

 WeakMapはキー/値のペアを格納するオブジェクト。Mapとは異なり、キーにはオブジェクトしか使用できない。さらにWeakMapではキーを列挙する手段が提供されていない。WeakMapでは格納するキーに対し弱参照のみを保持する。そのため、キーとして使われたオブジェクトがgarbage collectionで回収された場合、WeakMap内からそのキーおよび対応付けられた値は削除される。

 WeakMapコンストラクタはサブクラス化可能にデザインされている。その場合、サブクラスのコンストラクタ内ではsuperキーワードを使ってWeakMapコンストラクタを呼び出してインスタンスの初期化を行う必要がある。

 WeakMapオブジェクトを関数として実行する場合、newキーワード付きで実行する必要がある。引数にはiterableなオブジェクトを取る。

 WeakMapオブジェクトはprototypeプロパティを持つ。WeakMap.prototypeオブジェクトは下記のメソッド/プロパティを持つ。

WeakMap.prototype.constructor	コンストラクタ
WeakMap.prototype.delete(key)	keyに対応するキー/値のペアを削除する
WeakMap.prototype.get(key)	keyに対応する値を返す
WeakMap.prototype.has(key)	keyに対応するキーがあればtrue
WeakMap.prototype.set(key, value)	keyに対応する値をvalueにセットする
WeakMap.prototype[@@toStringTag]	"WeakMap"

第23章4節

 WeakSetはオブジェクトのセットを格納するオブジェクト。Setとは異なり、オブジェクトしか格納できない。WeakMapと同様、格納されているオブジェクトを列挙する手段は提供されておらず、格納するオブジェクトに対し弱参照のみを保持する。

 WeakSetコンストラクタはサブクラス化可能にデザインされている。その場合、サブクラスのコンストラクタ内ではsuperキーワードを使ってWeakSetコンストラクタを呼び出してインスタンスの初期化を行う必要がある。

 WeakSetオブジェクトを関数として実行する場合、newキーワード付きで実行する必要がある。引数にはiterableなオブジェクトを取る。

 WeakSetオブジェクトはprototypeプロパティを持つ。WeakSet.prototypeオブジェクトは下記のメソッド/プロパティを持つ。

WeakSet.prototype.add(value)	valueをセットに追加する
WeakSet.prototype.constructor	コンストラクタ
WeakSet.prototype.delete(value)	valueに対応する値をセットから削除する
WeakSet.prototype.has(value)	valueがセット内にあればtrue
WeakSet.prototype[@@toStringTag]	"WeakSet"

ECMAScript 2015の仕様書を読む(その17)

posted on 2016/05/18 00:49:06

 ECMAScript 2015の仕様書(ECMA-262)を読んでいます。今回はMapについて規定する第23章第1節とSetについて規定する第2節。

第23章1節

 Mapオブジェクトについて。任意のキーと値の組み合わせを格納できるオブジェクト。Mapコンストラクタはextendsでサブクラス化が可能。サブクラスのコンストラクタはsuperキーワードでMapコンストラクタを呼ぶ必要がある。

 Map()関数は必ずnewキーワード付きで呼び出す必要がある。引数にはiterableなオブジェクトを与えられる。また、Map.prototypeおよびMap[@@species]というプロパティを持つ。

 Map.prototypeは下記のメソッド/プロパティを持つ。

Map.prototype.clear()	格納しているキー/値をすべて空にする
Map.prototype.constructor	コンストラクタ
Map.prototype.delete(key)	keyに対応するキー/値を空にする
Map.prototype.entries()	キー/値を対象とするMapIteratorを返す
Map.prototype.forEach(callbackfn [, thisArg])	各要素のキー/値を引数にcallbackfnを呼び出す
Map.prototype.get(key)	keyに対応する値を返す
Map.prototype.has(key)	keyに対応するキーがあればtrue
Map.prototype.keys()	キーを対象とするMapIteratorを返す
Map.prototype.set(key, value)	keyというキーにvalueという値をセットする
Map.prototype.size	getter。サイズを返す
Map.prototype.values()	値を対象とするMapIteratorを返す
Map.prototype[@@iterator]()	entriesと同様
Map.prototype[@@toStringTag]	"Map"という文字列を返す

第23章2節

 Setオブジェクトについて。任意の値を格納できる。1つの値は1つしか格納できない。Setコンストラクタはサブクラス化可能で、その際はサブクラスのコンストラクタ内でsuperキーワードを使ってSetコンストラクタを呼ぶ必要がある。

 Set()関数は必ずnewキーワード付きで呼び出す必要がある。引数にはiterableなオブジェクトを与えられる。また、Set.prototypeおよびSet[@@species]というプロパティを持つ。

 Set.prototypeは下記のメソッド/プロパティを持つ。

Set.prototype.add(value)	指定した値を追加する
Set.prototype.clear()	格納している値をすべて取り除く
Set.prototype.constructor	コンストラクタ
Set.prototype.delete(value)	valueに対応する値を取り除く
Set.prototype.entries()	値を対象とするSetIteratorを返す
Set.prototype.forEach(callbackfn [, thisArg])	各値を引数にcallbackfnを呼び出す
Set.prototype.has(value)	valueに対応する値があればtrue
Set.prototype.keys()	値を対象とするSetIteratorを返す
Set.prototype.size	getter。サイズを返す
Set.prototype.values()	値を対象とするSetIteratorを返す
Set.prototype[@@iterator]()	valuesと同様
Set.prototype[@@toStringTag]	"Set"という文字列を返す

ECMAScript 2015の仕様書を読む(その16)

posted on 2016/05/16 22:56:04

 ECMAScript 2015の仕様書(ECMA-262)を読んでいます。今回はTypedArrayなどについて規定する第22章2節。

第22章2節

 TypedArrayはバイナリデータを格納するための配列状オブジェクト。格納可能な要素はInt8/Uint8/Uint8C/Int16/Uint16/Int32/Uint32/Float32/Float64のいずれかで、各要素はすべて同じ型である必要がある。各型ごとに異なる次の関数オブジェクトがコンストラクタとして用意されている。

Int8Array
Uint8Array
Uint8ClampedArray
Int16Array
Uint16Array
Int32Array
Uint32Array
Float32Array
Float64Array

 これらはすべて同じ引数を持ち、また同じprototypeを持つので、以下ではこれらのオブジェクトを%TypedArray%と表記する。

 %TypedArray%は異なる引数を持つ複数の形式で関数として呼び出せる。ただし、これらはすべてnewキーワード付き呼び出す必要がある。newキーワードなしで呼び出すと、TypeErrorを返す。

 コンストラクタに与えられる引数とその際の動作は下記のとおり。

%TypedArray%()	空のTypedArrayを返す
%TypedArray%(length)	指定した数の要素を持つTypedArrayを返す。各要素は0に設定される
%TypedArray%(typedArray)	typedArrayと同じ要素を持つTypedArrayを返す
%TypedArray%(object)	objectを元にTypedArrayを作成して返す
%TypedArray%(buffer [, byteOffset [, length]])	bufferのbtyeOffsetからlengthまでの部分を格納したTypedArrayを作成して返す

 %TypedArray%は下記のメソッド/プロパティを持つ。

%TypedArray%.from(source [, mapfn [, thisArg]])	sourceオブジェクトからTypedArrayを作成して返す。mapfnが指定された場合はこの関数を用いたmap処理が行われたあとに作成されたTypedArrayを返。
%TypedArray%.of(...items)	itemsを要素として持つTypedArrayを作成して返す
%TypedArray%[@@species]	gettter。thisを返す

 %TypedArray%.prototypeは下記のメソッド/プロパティを持つ。なお、とくに説明のないものについてはArray.prototypeの同名メソッド/プロパティと同じ処理を行う。

%TypedArray%.prototype.buffer	getter。格納するデータをbuffer形式で返す
%TypedArray%.prototype.byteLength	getter。格納するバイト数を返す
%TypedArray%.prototype.byteOffset	getter。byteOffsetを返す
%TypedArray%.prototype.constructor	コンストラクタ
%TypedArray%.prototype.copyWithin(target, start [, end])
%TypedArray%.prototype.entries()
%TypedArray%.prototype.every(callbackfn [, thisArg])
%TypedArray%.prototype.fill(value, [, start [, end]])
%TypedArray%.prototype.filter(callbackfn [, thisArg])
%TypedArray%.prototype.find(predicate [, thisArg])
%TypedArray%.prototype.findIndex(predicate [, thisArg])
%TypedArray%.prototype.forEach(callbackfn [, thisArg])
%TypedArray%.prototype.indexOf(searchElement [, fromIndex])
%TypedArray%.prototype.join(separator)
%TypedArray%.prototype.keys()
%TypedArray%.prototype.lastIndexOf(searchElement [, fromIndex])
%TypedArray%.prototype.length	格納する要素数
%TypedArray%.prototype.map(callbackfn [, thisArg])
%TypedArray%.prototype.reduce(callbackfn, [initialValue])
%TypedArray%.prototype.reduceRight(callbackfn, [initialValue])
%TypedArray%.prototype.set(overloaded [, offset])	第一引数からデータを読み込む。型によって処理が異なる
%TypedArray%.prototype.set(array [, offset])	arrayからデータを読み込む
%TypedArray%.prototype.set(typedArray [, offset])	typedArrayからデータを読み込む
%TypedArray%.prototype.slice(start, end)
%TypedArray%.prototype.some(callbackfn [, thisArg])
%TypedArray%.prototype.sort(comparefn)
%TypedArray%.prototype.subarray([begin [, end]])	部分配列を返す。この部分配列はバッファを共有する
%TypedArray%.prototype.toLocaleString([reserved1 [, reserved2]])
%TypedArray%.prototype.toString()
%TypedArray%.prototype.values()
%TypedArray%.prototype[@@iterator]()
%TypedArray%.prototype.[@@toStringTag]  getter。名前を返す

 なお、内部的に基底クラスとしてTypedArrayというものは存在するが、これをECMAScript 2015から直接操作することはできない。

 TypedArray.BYETS_PER_ELEMENTおよびTypedArray.prototype.BYTES_PER_ELEMENTで各要素のバイト数を参照できる。