[javascript]サンプルを実行

jsファイルにコードを書かないと簡単なサンプルも実行できない。

勿論、そんなものはオンラインにあるけど、そういうところにソースをパリッと貼り付けるのはご法度なケースも多いので・・・

パパッとjavascriptのサンプルをローカルなHTMLで実行するサンプルを作ってみた。

但し、new Functionからはグローバルな変数が見えてしまう。

それだけなら特に危なくないけど

某MS操縦士のセリフ:俺を踏み台にしたぁ~~~

なんてコードを書かれても不思議ではない碌でもない世の中なので、

ソースだけ公開。

<DOCTYPE html>
  <html lang="ja">

  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>javascriptを実行させるサンプル</title>
    <link href="jstest.css" media="all" rel="stylesheet" type="text/css" />
    <script src="createelement.js"></script>
    <script src="download.js"></script>
    <script src="jstest.js"></script>
    <link href="loader.css" media="all" rel="stylesheet" type="text/css" />
    <script src="loader.js"></script>
  </head>

  <body>
    <!-- loader begin -->
    <div id="js-loader" class="loader">
      <p>***</p>
      <p id="js-loader-text"></p>
      <p>***</p>
    </div>
    <!-- loader end -->
    <textarea class="jsText" id="jsText1" scrolling="auto">
// sample code
return new Promise((resolve, reject) => {
  let result = new Array(10);
  for (let index = 0; index < 10; index++) {
    result[index]=index + 1;
  }
  console.log(result); console.log(10);
  console.log('aaaaaaaaaaaaaa');
  console.log({log: 'data=> result=data' });
  resolve();
});
</textarea><br />
    <button type="button" id="executeJsText">実行</button><br />
    <div class="status" id="status"></div><br />
    <textarea class="jsResult" id="jsResult1" scrolling="auto"></textarea><br />
    <button type="button" id="downloadJsText">javaScriptダウンロード</button><br />
    <button type="button" id="downloadResult">結果ダウンロード</button><br />
  </body>

  </html>
@charset "UTF-8";

textarea.jsText {
    width: 95%;
    /* 親要素の幅と合わせる */
    height: 200px;
    resize: both;
    border: 2mm ridge rgba(211, 220, 50, .6);
}

textarea.jsResult {
    width: 95%;
    /* 親要素の幅と合わせる */
    height: 100px;
    resize: both;
    border: 2mm ridge rgba(211, 220, 50, .6);
}
let CRLF = '\r\n';
window.addEventListener('load', () => init());
/**
 * 初期化処理
 */
const init = () => {
    // ボタンクリックイベントの登録
    document.querySelector('#downloadJsText').addEventListener('click', () => downloadText('jsText1'));
    document.querySelector('#downloadResult').addEventListener('click', () => downloadText('jsResult1'));
    document.querySelector('#executeJsText').addEventListener('click', () => dexecuteJsText('jsText1', 'jsResult1'));
    loaderClose();
};
/**
 * サンプルをエンコーディングしたファイルをダウンロードする
 */
const downloadText = async (target) => {
    try {
        loaderOpen();
        try {
            let dateBegin = Date.now();
            displayStatus(`${target}ダウンロード処理中`);
            let jsText = document.querySelector(`#${target}`).value;
            download(jsText, `${target}.js`, "text/plan");
            displayStatus(`${target}ダウンロード完了。処理時間:${dateDateBetween(dateBegin, Date.now())}`);
        } catch (ex) {
            alert(`${target}ダウンロード異常終了${CRLF}${ex}`);
        }
        loaderClose();
    } catch (ex) {
        alert(ex);
    }
};
/**
 * 実行する
 * @param {*} jsText 
 * @param {*} jsResult 
 */
const dexecuteJsText = (jsText, jsResult) => {
    let jsTextElmText = document.querySelector(`#${jsText}`).value;
    let jsResultElm = document.querySelector(`#${jsResult} `);
    let dateBegin = Date.now();
    try {
        loaderOpen();
        try {
            displayStatus(`${jsText} 実行処理中`);
            let func = new Function('console', jsTextElmText);
            let result = [];
            let radix = 10;
            let rc = func({
                log: (data) => {
                    if (data === undefined) {
                        data = 'undefined';
                    }
                    if (data === null) {
                        data = 'null';
                    }
                    switch (typeof data) {
                        case 'object':
                            data = JSON.stringify(data);
                            break;
                        case 'string':
                            break;
                        default:
                            data = data.toString(radix);
                            break;
                    }
                    result.push(data);
                }
            });
            new Promise((resolve, reject) => {
                if (rc instanceof Promise) {
                    displayStatus(`${jsText} 実行中 Promise.then待ち`);
                    rc.then(() => {
                        resolve(result);
                    });
                } else {
                    resolve(result);
                }
            }).then((result) => {
                jsResultElm.innerHTML = result.join(CRLF);
                displayStatus(`${jsText} 実行完了。処理時間:${dateDateBetween(dateBegin, Date.now())} `);
            });
        } catch (ex) {
            displayStatus(`${jsText} 実行異常終了。処理時間:${dateDateBetween(dateBegin, Date.now())}${CRLF}${ex} `);
        }
        loaderClose();
    } catch (ex) {
        alert(ex);
    }
};
/**
 * ステータスを表示する
 * @param {string} text 
 */
const displayStatus = (text) => {
    let divStatus = document.querySelector('#status');
    divStatus.innerHTML = text;
    let divLoading = document.querySelector('#js-loader-text');
    divLoading.innerHTML = text;
};
/**
 * 時刻差のテキストを作成する
 * @param {Date} dateBegin 
 * @param {Date} dateEnd 
 * @returns 
 */
const dateDateBetween = (dateBegin, dateEnd) => {
    return `${(dateEnd - dateBegin) / 1000} 秒`
};

createelement.js
download.js
loader.css
loader.js

は先の記事

デスクトップに貼ったJSからSJISのCSVをダウンロードさせてみる【その後】サンプル

と同じなので割愛。

ミソはjsソース中に

console.log(result);

と書かれたらどうやって取り出すか?

である。

今回は

let result = "";
let func = new Function( 'console', jsテキスト);☚jsテキストの処理に対してパラメータ'console'を宣言
func({log: (data) => ☚{...}内がconsoleオブジェクトとして扱われ、result変数にセットされる。

これでjsテキストの中でconsole.logメソッドがそれっぽく動き出す。

jsコードがwindowやdocumentを直接参照するのが嫌なら

let func = new Function( 'console', 'window', 'document', ..., jsテキスト);
func(
{log: (data) => result.push(data);},
{console: (data) => xxxx;},
{body: (data) => xxxx;},
);

とパラメータを追加し、見せたい情報を渡してサンドバック風にできるだろう。




コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA