ホームページ ウェブフロントエンド jsチュートリアル JavaScriptで関数のシリアル化を行う方法 SpiderMonkey_基礎知識

JavaScriptで関数のシリアル化を行う方法 SpiderMonkey_基礎知識

May 16, 2016 pm 05:47 PM

Javascript では関数を簡単にシリアル化 (文字列化)、つまり関数のソース コードを取得できますが、実際にはこの操作の内部実装 (エンジン実装) は思っているほど単純ではありません。 SpiderMonkey では 2 つが使用されます。関数シリアル化テクノロジには 3 つあります。1 つは逆コンパイラを使用して、関数のコンパイルされたバイトコードをソース コード文字列に逆コンパイルするもので、もう 1 つは関数をバイトコードにコンパイルする前に関数のソース コードを圧縮するものです。

関数をシリアル化する方法
SpiderMonkey には、関数をシリアル化できるメソッドまたは関数が 3 つあります。 Function.prototype.toSource、unval。toString メソッドのみが標準です。つまり、すべてのエンジンに共通です。ただし、ES 標準 (ES5 15.3.4.2) には、Function.prototype.toString メソッドに関する説明がいくつかあります。 ) つまり、基本的に標準はなく、それをどのように実装するかはエンジンが決定します。

関数のシリアル化の主な役割は次のとおりです。シリアル化ソース コードによって生成された関数を使用して、この関数を再定義します。

コードをコピーします コードは次のとおりです:
function a() {
...
alert("a")
...
}

a() //"a" は可能性があります実行中にポップアップします

a = eval("(" a.toString().replace('alert("a")', 'alert("b")') ")")

a() // 実行時に "b" がポップアップ表示される場合があります


あなたは次のように考えているかもしれません。確かに、自分の Web サイトの場合は、js ファイルを完全に制御できます。このパッチ適用方法で関数を変更する必要はなく、直接変更するだけです。しかし、ソース ファイルが制御下にない場合は、たとえば、greasemonkey スクリプトが一般的に使用されます。Web サイトの機能を無効にしたり、変更したりする必要がある場合があります。Firefox 自体の特定の機能を変更する必要がある場合もあります。 Firefox は JS で書かれていると言っています)。これは私が書いた例です
Firefox スクリプトの例
:
コードをコピーします コードは次のとおりです。location == "chrome:/ /browser/content/browser.xul" && eval("gURLBar.handleCommand=" gURLBar.handleCommand.toString().replace( /^s*(load. );/gm, "/^javascript:/.test(url )||(content.location=='about:blank'||content.location=='about:newtab')? $1:gBrowser.loadOneTab(url,{postData:postData,inBackground:false,allowThirdPartyFixup: true}) ;"))
このコードの機能は次のとおりです: アドレス バーで Enter キーを押すと、Firefox が開きます。これを実現するには、toString メソッドを使用して gURLBar を読み取り、正規表現に置き換えて eval に渡して関数を再定義します。

それを直接定義しないのはなぜですか。つまり、関数を直接書き換えてください:

gURLBar.handleCommand = function(){...//元の関数を小さな場所で変更します}
これができない理由は、互換性を考慮する必要があるためです。そうであれば、この関数のソースコードはできるだけ変更しない方がよいでしょう。 書いてあるように、Firefox の gURLBar.handleCommand のソースコードが変更されると、このスクリプトになります。たとえば、Firefox3 と Firefox4 の両方にこの機能がありますが、機能の内容は大きく異なります。ただし、一部のキーワードを正規表現を使用して置き換える場合、このキーワードが変更されない限り、問題は発生します。


Decompile bytecode
SpiderMonkey では、関数はバイトコード (バイトコード) に解析された後にコンパイルされます。つまり、元の関数のソース コードが保存されます。 SpiderMonkey にはデコンパイラがあり、その主な機能は関数のバイトコードを関数ソース コードの形式に逆コンパイルすることです。
Firefox16 以前のバージョンでは、SpiderMonkey はこの方法を使用します。これらのバージョンの Firefox を使用している場合は、次のコードを試してください:


alert(function () {
"String";
//Comment
return 1 2 3
}.toString())
返される文字列は
です
関数 () {
戻り値
}


出力は他のブラウザとは完全に異なります:

1. 意味のないプリミティブ値リテラルはコンパイル中に削除されます。この例では、それは「文字列」です。

「問題ないようです。いずれにせよ、これらの値は関数の動作にとって意味がありません。待って、何か忘れていませんか?」と思われるかもしれません。これは strict を意味します。パターン文字列「use strict」はどうすればよいですか?

Firefox 3.6 などの strict モードをサポートしていないバージョンでは、この「use strict」は他の文字列と変わらないため削除されます。 SpiderMonkey が strict モードを実装した後は、コンパイル時に "use strict" という文字列も無視されますが、この関数が strict モードであるかどうかは、関数本体の先頭にあると判断されます。 「use strict」を 1 行に追加します。対応するエンジンのソース コードは次のとおりです。


コードをコピーします。 コードは次のとおりです。
DecompileBody(JSPrinter *jp, JSScript *script, jsbytecode *pc)
{
/* 必要に応じて、厳密モード コード ディレクティブを出力します。 . */
if (script->strictModeCode && !jp->strict) {
if (jp->fun && (jp->gt;fun->flags & JSFUN_EXPR_CLOSURE)) {
/*
* 厳密な関数式の構文はありません。
* 少なくともヒントを与えてください。
*/
js_printf(jp, "t/* use strict */ n");
} else {
js_printf(jp, "t"use strict";n");
}
jp->strict = true;

jsbytecode *end = script-> ;code script->length;
return DecompileCode(jp, script, pc, end - pc, 0);



2コンパイル中のコメントも削除されます

これはあまり影響がないようですが、一部の人々は関数のコメントを使用して複数行の文字列を実装します。 Firefox 17 より前のバージョン。


コードをコピー
コードは次のとおりです。 function hereDoc(f ) { return f.toString( ).replace(/^. s/,"").replace(/. $/,"");
} var string = hereDoc(function () {/*

あなた

*/});
console.log(string)



あなた

3. 元の値 リテラル操作はコンパイル時に実行されます

これは、「高性能 JavaScript」で説明されている

です。 逆コンパイルの欠点

新しいテクノロジー (厳密モードなど) の出現により、また他の関連バグを変更する場合、逆コンパイラのこの部分の実装を変更する必要があることがよくあります。変更により新しいバグが発生する可能性があります。私はこれを個人的に経験しました。おそらく Firefox 10 の頃でした。具体的な問題ははっきりとは覚えていませんが、おそらく次のようなものでした。 >

コードをコピー

コードは次のとおりです:
逆コンパイル時に括弧(a b) は省略されています。加算結合は左から右に進むため、問題ありません。しかし、私が遭遇したバグは次のとおりです。




コードをコピー


コードは次のとおりです:
これは機能しません。たとえば、a=1、b=2、c="3" の場合、a b c は "33" に等しくなります。 (b c) は "123 " に等しい。

逆コンパイラに関して、Mozilla エンジニアの Luke Wagner は、逆コンパイラがいくつかの新機能の実装を大きく妨げており、しばしばいくつかのバグを抱えていると指摘した。まだまだ続きますが、私も昨年、逆コンパイラーによる多大な影響を感じました。また、テストのカバレッジも低く、些細でない変更は必ずファズバグを生み出します。この影響を早く取り除くほど、より早く利益を得ることができます。特に、新しい言語機能のために大規模なフロントエンド/バイトコードのハッキングを行った後よりも、今がそれを削除するより良い時期だと思います。

Brendan Eich 氏は、逆コンパイラーには多くの欠点があるとも言いました。

私は逆コンパイラには愛がありません。17 年間ハッキングされ続けています。ストレージ関数のソース コード
Firefox17 以降、SpiderMonkey は 2 番目の実装方法に変更されました。他のブラウザもこの方法で実装する必要があります。空白文字やコメントなどを含めてソースコードと完全に一致しています。この場合、ほとんどの問題は解消されるはずですが、

については別の質問があるようです。例:


(function A() {
"use strict";
alert("A");
}) ""


もちろん、返されるソース コードには "use strict" も含まれている必要があります。すべてのブラウザで true これは実現されます:


関数A() {
"厳密な使用";
alert("A");


次の場合はどうなるでしょう:


コードをコピー コードは次のとおりです: (function A() {
"use strict";
return function B() {
alert( "B")
}
})() ""


内部関数 B も厳密モードである必要があります。 B? を出力する関数のソースコードに strict を追加します。試してみてください:
上記の通り、Firefox17 以前と Firefox4 以降のバージョンでは、現在の関数が含まれているかどうかを判断して、「use strict」を出力するかどうかを決定します。関数 B は関数 A の厳密モードを継承します。したがって、「厳密な使用」が行われます。

同時に、SpiderMonkey は逆コンパイルされたソース コードをフォーマットするため、厳密にインデントされます。前のソース コードにインデントがまったくない場合でもソース コード


function B() {
" use strict";
コードをコピー


コードは次のとおりです:

function B() {
"use strict";
alert(" B") } SpiderMonkey の最新バージョンの jsfun.cpp ソース コードには対応するコメントがあります// 関数の上位関数に「use strict」がある場合、この関数は上位関数の strict モードを継承します。
// また、「use strict」を挿入します。この内部関数の関数本体
// これにより、この関数の toString がメソッドの戻り値を再評価するときに、
// 再生成された関数が元の関数と同じセマンティクスを持つことが保証されます。


違いは、他のブラウザには「use strict」がないことです:



コードをコピーします


コードは次のとおりです。


function B() {
alert("B")
}
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? Apr 04, 2025 pm 02:42 PM

フロントエンドのサーマルペーパーチケット印刷のためのよくある質問とソリューションフロントエンド開発におけるチケット印刷は、一般的な要件です。しかし、多くの開発者が実装しています...

誰がより多くのPythonまたはJavaScriptを支払われますか? 誰がより多くのPythonまたはJavaScriptを支払われますか? Apr 04, 2025 am 12:09 AM

スキルや業界のニーズに応じて、PythonおよびJavaScript開発者には絶対的な給与はありません。 1. Pythonは、データサイエンスと機械学習でさらに支払われる場合があります。 2。JavaScriptは、フロントエンドとフルスタックの開発に大きな需要があり、その給与もかなりです。 3。影響要因には、経験、地理的位置、会社の規模、特定のスキルが含まれます。

javascriptの分解:それが何をするのか、なぜそれが重要なのか javascriptの分解:それが何をするのか、なぜそれが重要なのか Apr 09, 2025 am 12:07 AM

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

JavaScriptを使用して、同じIDを持つArray要素を1つのオブジェクトにマージする方法は? JavaScriptを使用して、同じIDを持つArray要素を1つのオブジェクトにマージする方法は? Apr 04, 2025 pm 05:09 PM

同じIDを持つ配列要素をJavaScriptの1つのオブジェクトにマージする方法は?データを処理するとき、私たちはしばしば同じIDを持つ必要性に遭遇します...

Shiseidoの公式Webサイトのように、視差スクロールと要素のアニメーション効果を実現する方法は?
または:
Shiseidoの公式Webサイトのようにスクロールするページを伴うアニメーション効果をどのように実現できますか? Shiseidoの公式Webサイトのように、視差スクロールと要素のアニメーション効果を実現する方法は? または: Shiseidoの公式Webサイトのようにスクロールするページを伴うアニメーション効果をどのように実現できますか? Apr 04, 2025 pm 05:36 PM

この記事の視差スクロールと要素のアニメーション効果の実現に関する議論では、Shiseidoの公式ウェブサイト(https://www.shisido.co.co.jp/sb/wonderland/)と同様の達成方法について説明します。

JavaScriptは学ぶのが難しいですか? JavaScriptは学ぶのが難しいですか? Apr 03, 2025 am 12:20 AM

JavaScriptを学ぶことは難しくありませんが、挑戦的です。 1)変数、データ型、関数などの基本概念を理解します。2)非同期プログラミングをマスターし、イベントループを通じて実装します。 3)DOM操作を使用し、非同期リクエストを処理することを約束します。 4)一般的な間違いを避け、デバッグテクニックを使用します。 5)パフォーマンスを最適化し、ベストプラクティスに従ってください。

Console.log出力の違い結果:なぜ2つの呼び出しが異なるのですか? Console.log出力の違い結果:なぜ2つの呼び出しが異なるのですか? Apr 04, 2025 pm 05:12 PM

Console.log出力の違いの根本原因に関する詳細な議論。この記事では、Console.log関数の出力結果の違いをコードの一部で分析し、その背後にある理由を説明します。 �...

フロントエンド開発でVSCodeと同様に、パネルドラッグアンドドロップ調整機能を実装する方法は? フロントエンド開発でVSCodeと同様に、パネルドラッグアンドドロップ調整機能を実装する方法は? Apr 04, 2025 pm 02:06 PM

フロントエンドのVSCodeと同様に、パネルドラッグアンドドロップ調整機能の実装を調べます。フロントエンド開発では、VSCODEと同様のVSCODEを実装する方法...

See all articles