kyranrana/simple-javascript-compilation

通过一系列操作编译 JavaScript 代码。

0.3.1 2019-09-17 21:20 UTC

This package is auto-updated.

Last update: 2020-05-17 23:34:35 UTC


README

CircleCI

此库支持编译简单的 JavaScript 声明和表达式,无需 PHP V8JS。

支持的表达式

- Global methods

    - String.fromCharCode
    - atob
    - eval
    - escape

- Primitive types

    - Boolean  
    - Integer
    
        - toFixed
    
    - String
    
       - charCodeAt
       - italics
       - length
    
    - Null
    - Undefined 

- Arrays

架构

此库由 4 个主要类组成。

ExpressionStreamReader
  • 读取并通过事件发射表达式的关键区域。

  • 发射的事件

    • EXPRESSION_START
    {
        castAndNegations:   Array<String>           // casts and negations (! +) before expression
    }
    
    • EXPRESSION_END
    {
        additionalOps:      Array<AdditionalCall>   // function and index calls on result of expression
        operator:           Operator                // operator
    }
    
    • ARRAY_START
    {
        castAndNegations:   Array<String>           // casts and negations (! +) before array
    }
    
    • ARRAY_END
    {
        additionalOps:      Array<AdditionalCall>   // function and index calls on result of array
        operator:           Operator                // operator
    }
    
    • BOOLEAN
    {
        value:              String                  // true / false
        additionalOps:      Array<AdditionalCall>   // function or index calls on boolean
        castsAndNegations:  Array<String>           // casts and negations (! +) before boolean
        operator:           Operator                // operator
    }
    
    • INTEGER
    {
        value:              String                  // integer / NaN / Infinity / -Infinity
        additionalOps:      Array<AdditionalCall>   // function or index calls on integer
        castsAndNegations:  Array<String>           // casts and negations (! +) before integer
        operator:           Operator                // operator
    }
    
    • STRING
    {
       value:              String                  // string
       additionalOps:      Array<AdditionalCall>   // function or index calls on string
       castsAndNegations:  Array<String>           // casts and negations (! +) before string
       operator:           Operator                // operator
    }
    
    • NULL
    {
        value:              String                  // null
        additionalOps:      Array<AdditionalCall>   // functions or index calls on null
        castsAndNegations:  Array<String>           // casts and negations (! +) before null
        operator:           Operator                // operator
    }
    
    • UNDEFINED
    {
        value:              String                  // undefined
        additionalOps:      Array<AdditionalCall>   // functions or index calls on undefined
        castsAndNegations:  Array<String>           // casts and negations (! +) before undefined
        operator:           Operator                // operator
    }
    
    • DEFINITION
    {
        name:               String                  // definition name
        additionalOps:      Array<AdditionalCall>   // function or index calls on definition value
        castsAndNegations:  Array<String>           // casts and negations (! +) before definition
        operator:           Operator                // operator
    }
    
    • FUNCTION_START
    {
        castsAndNegations:  Array<String>           // casts and negations (! +) before function call
    }
    
    • FUNCTION_NAME
    {
        name:               String                  // function name
    }
    
    • FUNCTION_ARG
    {
        argData:            Array<Event>            // collection of expression events 
    }
    
    • FUNCTION_END
    {
        additionalOps:      Array<AdditionalCall>   // function or index calls on function
        operator:           Array<String>           // operator
    }
    
    • INLINE_FUNCTION_START
    {
        castsAndNegations:  Array<String>           // casts and negations (! +) before inline function
    }
    
    • INLINE_FUNCTION_ARG
    {
        arg:                Array<Event>            // collection of expression events
    }
    
    • INLINE_FUNCTION_CODE
    {
        value:              String                  // inline function code
    }
    
    • INLINE_FUNCTION_ARG_DATA
    {
        argData:             Array<Event>            // collection of expression events
    }
    
    • INLINE_FUNCTION_END
    {
        additionalOps:      Array<AdditionalCall>   // function or index calls on inline function
        operator:           Operator                // operator
    }
    
    • FUNCTION_ONLY
    {
        castsAndNegations:  Array<String>           // casts and negations (! +) before function name
        name:               String                  // function name
        operator:           Operator                // operator
    }
    
  • 使用的模型

    • AdditionalCall
    {
        type:               String                  // property or function
        name:               Array<Events>           // property or function name
        args:               Array<Array<Event>>     // function arguments
    }
    
DeclarationStreamReader
  • 读取并发射代码中每个声明的事件,代码仅包含声明。

  • 发射的事件

    • DECLARATION
    {
        declaration:        String                  // declaration name
        operator:           Operator                // operator
        value:              String                  // expression
    }
    
    
ExpressionInterpreter
  • 使用 ExpressionStreamReader 和在内部函数使用时 DeclarationInterpreter 来解析表达式,最终返回 CustomDataType
<?php
use SimpleJavaScriptCompilation\ExpressionInterpreterImpl;
use SimpleJavaScriptCompilation\Model\Context;

$customDataType = ExpressionInterpreterImpl::instance()->interpretExpression('2+2+"hey there"', new Context());
?>
  • 在解析表达式的过程中维护一个 Context,它包含处理表达式特定区域所需的数据。如果您想向表达式解析器传递自己的定义,可以执行以下操作
<?php
use SimpleJavaScriptCompilation\ExpressionInterpreterImpl;
use SimpleJavaScriptCompilation\Model\Context;
use SimpleJavaScriptCompilation\Model\DataType\CustomString;
use SimpleJavaScriptCompilation\Model\DataType\CustomInteger;
use SimpleJavaScriptCompilation\Model\DataType;

$ctx = new Context();
$ctx->setCtxVar("a", new CustomInteger(new DataType(["value" => "2"])));
$ctx->setCtxVar("c", new CustomString(new DataType(["value" => '"hello, "'])));

// You can also set functions in the context too
// See a list of supported functions in SimpleJavaScriptCompilation\Model\FunctionMap\GlobalFunctionMap
$ctx->setCtxFunc("e", "SimpleJavaScriptCompilation\Model\FunctionMap\GlobalFunctionMap::atob");

$customDataType = ExpressionInterpreterImpl::instance()->interpretExpression('a+2+c+"hey there"+(function(){ return "sup"; })()', $ctx);
?>
  • 更多使用示例可以在 /src/test/ExpressionInterpreterImplTest.php 中找到

  • 覆盖的模型

    • Context
    {
        ctxStack:       Array<Mixed>                        // INTERNAL ONLY
        ctxTmp:         Array<String, Mixed>                // INTERNAL ONLY
        ctxVarMap:      Array<String, CustomDataType>       // variables 
        ctxFuncMap:     Array<String, Mixed>                // functions
        ctxSum:         CustomDataType                      // computed result to start calculation with
    }
    
    • CustomDataType
    {
        dataType:       DataType                            // underlying data type model
        
        merge(DataType $dataType): CustomDataType
        add(DataType $dataType): CustomDataType             // adds data type models and determines new CustomDataType
        subtract(DataType $dataType): CustomDataType        // subtracts data type models and determines new CustomDataType
        multiply(DataType $dataType): CustomDataType        // multiplies data type models and determines new CustomDataType
        divide(DataType $dataType): CustomDataType          // divides data type models and determines new CustomDataType
    }
    
    • CustomDataType 实现们

      • CustomInteger - 处理 JavaScript 整数的计算(数字 / NaN / Infinity)
      • CustomString - 处理 JavaScript 字符串的计算
      • CustomBoolean - 处理 JavaScript 布尔值的计算(true / false)
      • CustomNull - 处理 JavaScript null 的计算
      • CustomUndefined - 处理 JavaScript undefined 的计算
    • DataType

    {
        dataType:               DataTypeEnum                // type of data
        castsAndNegations:      Array<String>               // casts and negations (! +) before data type
        value:                  String                      // data type value
        additionalCalls:        Array<AdditionalCall>       // function or index calls on data type value
        operator:               Operator                    // operator
    }
    
DeclarationInterpreter
  • 使用 DeclarationStreamReaderExpressionInterpreter 解析一组声明,最终返回 Context
<?php
use SimpleJavaScriptCompilation\DeclarationInterpreterImpl;
use SimpleJavaScriptCompilation\Model\Context;

$ctx = DeclarationInterpreterImpl::instance()->interpretDeclarations('var a = 2+2; var b = "hey there";', new Context());
?>
<?php
use SimpleJavaScriptCompilation\DeclarationInterpreterImpl;
use SimpleJavaScriptCompilation\Model\DataType\CustomInteger;
use SimpleJavaScriptCompilation\Model\Context;
use SimpleJavaScriptCompilation\Model\DataType;

// You can also pass your own variables and functions to the context
// Refer to examples in ExpressionInterpreter section
$ctx = new Context();
$ctx->setCtxVar("a", new CustomInteger(new DataType(['value' => '4'])));

$ctx = DeclarationInterpreterImpl::instance()->interpretDeclarations('var a = 2+2; var b = "hey there";', $ctx);
?>
  • 更多使用示例可以在 /src/test/DeclarationInterpreterImplTest.php 中找到