修改V8和node.js建立中文后端开发工具

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 修改V8编译器源码, 实现关键词的中文化. Modify source code of V8 JavaScript compiler to support keywords in Chinese.

本文github: https://github.com/swizl/zwnode

一. 修改V8

V8在一个文件里改就行了。

depsv8srcparsingscanner.cc

  1. 从llvm中下一个轮子过来的StringSwitch,当然要改一下。StringRef改成std::wstring, 多余的功能去掉。放在 scanner.cc 开头。

狗屎咖啡:为clang添加中文关键字​

template<typename T, typename R = T>
class StringSwitch {
  std::wstring Str;
  const T *Result;

public:
  //
  explicit StringSwitch(std::wstring S)
  : Str(S), Result(nullptr) { }

  // StringSwitch is not copyable.
  StringSwitch(const StringSwitch &) = delete;
  void operator=(const StringSwitch &) = delete;

  StringSwitch(StringSwitch &&other) {
    *this = std::move(other);
  }
  StringSwitch &operator=(StringSwitch &&other) {
    Str = other.Str;
    Result = other.Result;
    return *this;
  }

  ~StringSwitch() = default;

  // Case-sensitive case matchers
  template<unsigned N>
  StringSwitch& Case(const wchar_t (&S)[N], const T& Value) {
    assert(N);
    if (!Result && N-1 == Str.size() &&
        //(N == 1 || std::memcmp(S, Str.data(), (N-1)*sizeof(wchar_t)) == 0)) {
        (N == 1 || Str.compare(S) == 0)) {
      Result = &Value;
    }
    return *this;
  }

  R Default(const T &Value) const {
    if (Result)
      return *Result;
    return Value;
  }

  
  operator R() const {
    assert(Result && "Fell off the end of a string-switch");
    return *Result;
  }
};
  1. 加上中文的关键字和英文关键字一样对应, 可以根据自己的喜好随便改。
#define KEYWORDS(KEYWORD_GROUP, KEYWORD, ZWKEYWORD)                    \
  KEYWORD_GROUP('a')                                        \
  KEYWORD("arguments", Token::ARGUMENTS)                    \
  ZWKEYWORD("诸参", Token::ARGUMENTS)                    \
  KEYWORD("as", Token::AS)                                  \
  ZWKEYWORD("以", Token::AS)                                  \
  KEYWORD("async", Token::ASYNC)                            \
  ZWKEYWORD("异", Token::ASYNC)                            \
  KEYWORD("await", Token::AWAIT)                            \
  ZWKEYWORD("等", Token::AWAIT)                            \
  KEYWORD("anonymous", Token::ANONYMOUS)                    \
  ZWKEYWORD("匿", Token::ANONYMOUS)                    \
  KEYWORD_GROUP('b')                                        \
  KEYWORD("break", Token::BREAK)                            \
  ZWKEYWORD("破", Token::BREAK)                            \
  KEYWORD_GROUP('c')                                        \
  KEYWORD("case", Token::CASE)                              \
  ZWKEYWORD("例", Token::CASE)                              \
  KEYWORD("catch", Token::CATCH)                            \
  ZWKEYWORD("捕", Token::CATCH)                            \
  KEYWORD("class", Token::CLASS)                            \
  ZWKEYWORD("类", Token::CLASS)                            \
  KEYWORD("const", Token::CONST)                            \
  ZWKEYWORD("常", Token::CONST)                            \
  KEYWORD("constructor", Token::CONSTRUCTOR)                \
  ZWKEYWORD("构造器", Token::CONSTRUCTOR)                \
  KEYWORD("continue", Token::CONTINUE)                      \
  ZWKEYWORD("继", Token::CONTINUE)                      \
  KEYWORD_GROUP('d')                                        \
  KEYWORD("debugger", Token::DEBUGGER)                      \
  ZWKEYWORD("调试器", Token::DEBUGGER)                      \
  KEYWORD("default", Token::DEFAULT)                        \
  ZWKEYWORD("默", Token::DEFAULT)                        \
  KEYWORD("delete", Token::DELETE)                          \
  ZWKEYWORD("删", Token::DELETE)                          \
  KEYWORD("do", Token::DO)                                  \
  ZWKEYWORD("行", Token::DO)                                  \
  KEYWORD_GROUP('e')                                        \
  KEYWORD("else", Token::ELSE)                              \
  ZWKEYWORD("另", Token::ELSE)                              \
  KEYWORD("enum", Token::ENUM)                              \
  ZWKEYWORD("举", Token::ENUM)                              \
  KEYWORD("eval", Token::EVAL)                              \
  ZWKEYWORD("估", Token::EVAL)                              \
  KEYWORD("export", Token::EXPORT)                          \
  ZWKEYWORD("导", Token::EXPORT)                          \
  KEYWORD("extends", Token::EXTENDS)                        \
  ZWKEYWORD("承", Token::EXTENDS)                        \
  KEYWORD_GROUP('f')                                        \
  KEYWORD("false", Token::FALSE_LITERAL)                    \
  ZWKEYWORD("假", Token::FALSE_LITERAL)                    \
  KEYWORD("finally", Token::FINALLY)                        \
  ZWKEYWORD("末", Token::FINALLY)                        \
  KEYWORD("for", Token::FOR)                                \
  ZWKEYWORD("于", Token::FOR)                                \
  KEYWORD("from", Token::FROM)                              \
  ZWKEYWORD("从", Token::FROM)                              \
  KEYWORD("function", Token::FUNCTION)                      \
  ZWKEYWORD("函数", Token::FUNCTION)                      \
  KEYWORD_GROUP('g')                                        \
  KEYWORD("get", Token::GET)                                \
  ZWKEYWORD("取", Token::GET)                                \
  KEYWORD_GROUP('i')                                        \
  KEYWORD("if", Token::IF)                                  \
  ZWKEYWORD("如", Token::IF)                                  \
  KEYWORD("implements", Token::FUTURE_STRICT_RESERVED_WORD) \
  ZWKEYWORD("成", Token::FUTURE_STRICT_RESERVED_WORD) \
  KEYWORD("import", Token::IMPORT)                          \
  ZWKEYWORD("引", Token::IMPORT)                          \
  KEYWORD("in", Token::IN)                                  \
  ZWKEYWORD("在", Token::IN)                                  \
  KEYWORD("instanceof", Token::INSTANCEOF)                  \
  ZWKEYWORD("是为", Token::INSTANCEOF)                  \
  KEYWORD("interface", Token::FUTURE_STRICT_RESERVED_WORD)  \
  ZWKEYWORD("接", Token::FUTURE_STRICT_RESERVED_WORD)  \
  KEYWORD_GROUP('l')                                        \
  KEYWORD("let", Token::LET)                                \
  ZWKEYWORD("让", Token::LET)                                \
  KEYWORD_GROUP('m')                                        \
  KEYWORD("meta", Token::META)                              \
  ZWKEYWORD("元", Token::META)                                \
  KEYWORD_GROUP('n')                                        \
  KEYWORD("name", Token::NAME)                              \
  ZWKEYWORD("名", Token::NAME)                              \
  KEYWORD("new", Token::NEW)                                \
  ZWKEYWORD("新", Token::NEW)                                \
  KEYWORD("null", Token::NULL_LITERAL)                      \
  ZWKEYWORD("无", Token::NULL_LITERAL)                      \
  KEYWORD_GROUP('o')                                        \
  KEYWORD("of", Token::OF)                                  \
  ZWKEYWORD("之", Token::OF)                                  \
  KEYWORD_GROUP('p')                                        \
  KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD)    \
  ZWKEYWORD("包", Token::FUTURE_STRICT_RESERVED_WORD)    \
  KEYWORD("private", Token::FUTURE_STRICT_RESERVED_WORD)    \
  ZWKEYWORD("私", Token::FUTURE_STRICT_RESERVED_WORD)    \
  KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD)  \
  ZWKEYWORD("保", Token::FUTURE_STRICT_RESERVED_WORD)  \
  KEYWORD("prototype", Token::PROTOTYPE)                    \
  ZWKEYWORD("原型", Token::PROTOTYPE)                    \
  KEYWORD("public", Token::FUTURE_STRICT_RESERVED_WORD)     \
  ZWKEYWORD("公", Token::FUTURE_STRICT_RESERVED_WORD)     \
  KEYWORD_GROUP('r')                                        \
  KEYWORD("return", Token::RETURN)                          \
  ZWKEYWORD("返", Token::RETURN)                          \
  KEYWORD_GROUP('s')                                        \
  KEYWORD("set", Token::SET)                                \
  ZWKEYWORD("设", Token::SET)                                \
  KEYWORD("static", Token::STATIC)                          \
  ZWKEYWORD("固", Token::STATIC)                          \
  KEYWORD("super", Token::SUPER)                            \
  ZWKEYWORD("超", Token::SUPER)                            \
  KEYWORD("switch", Token::SWITCH)                          \
  ZWKEYWORD("切", Token::SWITCH)                          \
  KEYWORD_GROUP('t')                                        \
  KEYWORD("target", Token::TARGET)                          \
  ZWKEYWORD("标", Token::TARGET)                          \
  KEYWORD("this", Token::THIS)                              \
  ZWKEYWORD("此", Token::THIS)                              \
  KEYWORD("throw", Token::THROW)                            \
  ZWKEYWORD("抛", Token::THROW)                            \
  KEYWORD("true", Token::TRUE_LITERAL)                      \
  ZWKEYWORD("真", Token::TRUE_LITERAL)                      \
  KEYWORD("try", Token::TRY)                                \
  ZWKEYWORD("试", Token::TRY)                                \
  KEYWORD("typeof", Token::TYPEOF)                          \
  ZWKEYWORD("之型", Token::TYPEOF)                          \
  KEYWORD_GROUP('u')                                        \
  KEYWORD("undefined", Token::UNDEFINED)                    \
  ZWKEYWORD("未定", Token::UNDEFINED)                    \
  KEYWORD_GROUP('v')                                        \
  KEYWORD("var", Token::VAR)                                \
  ZWKEYWORD("变", Token::VAR)                                \
  KEYWORD("void", Token::VOID)                              \
  ZWKEYWORD("空", Token::VOID)                              \
  KEYWORD_GROUP('w')                                        \
  KEYWORD("while", Token::WHILE)                            \
  ZWKEYWORD("当", Token::WHILE)                            \
  KEYWORD("with", Token::WITH)                              \
  ZWKEYWORD("为之", Token::WITH)                              \
  KEYWORD_GROUP('y')                                        \
  KEYWORD("yield", Token::YIELD)                            \
  ZWKEYWORD("降", Token::YIELD)                            \
  KEYWORD_GROUP('_')                                        \
  KEYWORD("__proto__", Token::PROTO_UNDERSCORED)            \
  ZWKEYWORD("__原__", Token::PROTO_UNDERSCORED)              \
  KEYWORD_GROUP('#')                                        \
  KEYWORD("#constructor", Token::PRIVATE_CONSTRUCTOR)        \
  ZWKEYWORD("#构造器", Token::PRIVATE_CONSTRUCTOR)

3.仿照KeywordOrIdentifierToken写一个ZWKeywordOrIdentifierToken

static Token::Value KeywordOrIdentifierToken(const uint8_t* input,
                                             int input_length) {
  DCHECK_GE(input_length, 1);
  const int kMinLength = 2;
  const int kMaxLength = 12;
  if (input_length < kMinLength || input_length > kMaxLength) {
    return Token::IDENTIFIER;
  }
  switch (input[0]) {
    default:
#define ZWKEYWORD(keyword, token)
#define KEYWORD_GROUP_CASE(ch)                                \
      break;                                                  \
    case ch:
#define KEYWORD(keyword, token)                                           \
  {                                                                       \
    /* 'keyword' is a char array, so sizeof(keyword) is */                \
    /* strlen(keyword) plus 1 for the NUL char. */                        \
    const int keyword_length = sizeof(keyword) - 1;                       \
    STATIC_ASSERT(keyword_length >= kMinLength);                          \
    STATIC_ASSERT(keyword_length <= kMaxLength);                          \
    DCHECK_EQ(input[0], keyword[0]);                                      \
    DCHECK(token == Token::FUTURE_STRICT_RESERVED_WORD ||                 \
           0 == strncmp(keyword, Token::String(token), sizeof(keyword))); \
    if (input_length == keyword_length && input[1] == keyword[1] &&       \
        (keyword_length <= 2 || input[2] == keyword[2]) &&                \
        (keyword_length <= 3 || input[3] == keyword[3]) &&                \
        (keyword_length <= 4 || input[4] == keyword[4]) &&                \
        (keyword_length <= 5 || input[5] == keyword[5]) &&                \
        (keyword_length <= 6 || input[6] == keyword[6]) &&                \
        (keyword_length <= 7 || input[7] == keyword[7]) &&                \
        (keyword_length <= 8 || input[8] == keyword[8]) &&                \
        (keyword_length <= 9 || input[9] == keyword[9]) &&                \
        (keyword_length <= 10 || input[10] == keyword[10])) {             \
      return token;                                                       \
    }                                                                     \
  }
      KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD, ZWKEYWORD)
  }
  return Token::IDENTIFIER;
//#undef KEYWORDS
#undef KEYWORD
#undef KEYWORD_GROUP_CASE
#undef ZWKEYWORD
}

#define IS_WCHAR_EQ_U16() (sizeof(wchar_t) == sizeof(uint16_t))
static Token::Value ZWKeywordOrIdentifierToken(const uint16_t* input,
                                             int input_length) {

#define ZWKEYWORD(keyword, token) .Case(L##keyword, token)
#define KEYWORD_GROUP_CASE(ch)
#define KEYWORD(keyword, token)
        std::wstring temp_input;
        if (IS_WCHAR_EQ_U16())
            temp_input.append((const wchar_t *)input, input_length);
        else for (int i = 0; i < input_length; ++i)
            temp_input.push_back((wchar_t)input[i]);
        return StringSwitch<Token::Value>(temp_input)
        KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD, ZWKEYWORD)
            .Default(Token::IDENTIFIER);
#undef KEYWORD
#undef KEYWORD_GROUP_CASE
#undef ZWKEYWORD
#undef KEYWORDS
}
  1. 在 ScanIdentifierOrKeywordInner 或 ScanIdentifierOrKeyword 中添加中文关键字返回token的逻辑,

node.js的稳点版,改点在ScanIdentifierOrKeyword中:

  if (next_.literal_chars->is_one_byte()) {
    Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
    Token::Value token =
        KeywordOrIdentifierToken(chars.start(), chars.length());
    if (token == Token::IDENTIFIER ||
        token == Token::FUTURE_STRICT_RESERVED_WORD ||
        Token::IsContextualKeyword(token))
      literal.Complete();
    return token;
  }  else {
    Vector<const uint16_t> chars = next_.literal_chars->two_byte_literal();
    Token::Value token =
        ZWKeywordOrIdentifierToken(chars.start(), chars.length());
    if (token == Token::IDENTIFIER ||
        token == Token::FUTURE_STRICT_RESERVED_WORD ||
        Token::IsContextualKeyword(token))
      literal.Complete();
    return token;
  }

node.js在github上的master,改点在ScanIdentifierOrKeywordInner中:

if (next_.literal_chars->is_one_byte()) {
    Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
    Token::Value token =
        KeywordOrIdentifierToken(chars.start(), chars.length());
    /* TODO(adamk): YIELD should be handled specially. */
    if (token == Token::FUTURE_STRICT_RESERVED_WORD) {
      literal->Complete();
      if (escaped) return Token::ESCAPED_STRICT_RESERVED_WORD;
      return token;
    }
    if (token == Token::IDENTIFIER || Token::IsContextualKeyword(token)) {
      literal->Complete();
      return token;
    }

    if (!escaped) return token;

    literal->Complete();
    if (token == Token::LET || token == Token::STATIC) {
      return Token::ESCAPED_STRICT_RESERVED_WORD;
    }
    return Token::ESCAPED_KEYWORD;
  } else {
    Vector<const uint8_t> chars = next_.literal_chars->two_byte_literal();
    Token::Value token =
        ZWKeywordOrIdentifierToken(chars.start(), chars.length());
    /* TODO(adamk): YIELD should be handled specially. */
    if (token == Token::FUTURE_STRICT_RESERVED_WORD) {
      literal->Complete();
      if (escaped) return Token::ESCAPED_STRICT_RESERVED_WORD;
      return token;
    }
    if (token == Token::IDENTIFIER || Token::IsContextualKeyword(token)) {
      literal->Complete();
      return token;
    }

    if (!escaped) return token;

    literal->Complete();
    if (token == Token::LET || token == Token::STATIC) {
      return Token::ESCAPED_STRICT_RESERVED_WORD;
    }
    return Token::ESCAPED_KEYWORD;
  }

二. 修改node.js的 js库,对内置对象和函数添加中文名称

修改实例:

添加 “控制台.日志” 等效 “console.log”

1.添加 “console” 中文名 “控制台”.

libinternalbootstrapnode.js // github master

libinternalbootstrap_node.js // web download

    Object.defineProperty(global, 'console', {
      configurable: true,
      enumerable: true,
      get() {
        return wrappedConsole;
        }
    });
    // 仿照添加 “控制台” 等效 “console”
    Object.defineProperty(global, '控制台', {
      configurable: true,
      enumerable: true,
      get() {
        return wrappedConsole;
       }
    });
  1. 添加 “log” 函数中文名 “日志”

libconsole.js:

Console.prototype.debug = Console.prototype.log;
// 仿照debug和info,添加一条“日志” 等效 “log”
Console.prototype.日志 = Console.prototype.log;

Console.prototype.info = Console.prototype.log;

三 编译

./configure
make all

四 运行实例:

hello.js //放在了 out/Release 中

函数 说1(词) {
    控制台.日志(词);
}
函数 执行(某函数, 值) {
    某函数(值);
}
变 你 = "你";
变 哈哈 = {
    哈1: '好',
     哈2: 12
}

执行(说1, 你);
控制台.日志(哈哈);

运行:

cd out/Release
./node hello.js

结果:

你
{ '哈1': '好', '哈2': 12 }

2018-09-19

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
29天前
|
存储 JavaScript 前端开发
深入浅出Node.js后端开发
在数字化时代的浪潮中,后端开发作为连接用户与数据的桥梁,扮演着至关重要的角色。本文将以Node.js为例,深入探讨其背后的哲学思想、核心特性以及在实际项目中的应用,旨在为读者揭示Node.js如何优雅地处理高并发请求,并通过实践案例加深理解。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供新的视角和思考。
|
26天前
|
Web App开发 开发框架 JavaScript
深入浅出Node.js后端开发
本文将带你领略Node.js的魅力,从基础概念到实践应用,一步步深入理解并掌握Node.js在后端开发中的运用。我们将通过实例学习如何搭建一个基本的Web服务,探讨Node.js的事件驱动和非阻塞I/O模型,以及如何利用其强大的生态系统进行高效的后端开发。无论你是前端开发者还是后端新手,这篇文章都会为你打开一扇通往全栈开发的大门。
|
29天前
|
Web App开发 开发框架 JavaScript
深入浅出Node.js后端开发
在这篇文章中,我们将一起探索Node.js的奇妙世界。无论你是刚接触后端开发的新手,还是希望深化理解的老手,这篇文章都适合你。我们将从基础概念开始,逐步深入到实际应用,最后通过一个代码示例来巩固所学知识。让我们一起开启这段旅程吧!
|
25天前
|
Web App开发 JavaScript 前端开发
深入浅出Node.js后端开发
本文将带领读者从零基础开始,一步步深入到Node.js后端开发的精髓。我们将通过通俗易懂的语言和实际代码示例,探索Node.js的强大功能及其在现代Web开发中的应用。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供新的见解和技巧,让你的后端开发技能更上一层楼。
|
28天前
|
JavaScript 前端开发 API
深入理解Node.js事件循环及其在后端开发中的应用
本文旨在揭示Node.js的核心特性之一——事件循环,并探讨其对后端开发实践的深远影响。通过剖析事件循环的工作原理和关键组件,我们不仅能够更好地理解Node.js的非阻塞I/O模型,还能学会如何优化我们的后端应用以提高性能和响应能力。文章将结合实例分析事件循环在处理大量并发请求时的优势,以及如何避免常见的编程陷阱,从而为读者提供从理论到实践的全面指导。
|
28天前
|
JavaScript
如何使用内存快照分析工具来分析Node.js应用的内存问题?
需要注意的是,不同的内存快照分析工具可能具有不同的功能和操作方式,在使用时需要根据具体工具的说明和特点进行灵活运用。
41 3
|
17天前
|
存储 缓存 负载均衡
后端开发中的性能优化策略
本文将探讨几种常见的后端性能优化策略,包括代码层面的优化、数据库查询优化、缓存机制的应用以及负载均衡的实现。通过这些方法,开发者可以显著提升系统的响应速度和处理能力,从而提供更好的用户体验。
44 4
|
8天前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
37 3
|
23天前
|
存储 前端开发 Java
深入理解后端开发:从基础到高级
本文将带你走进后端开发的神秘世界,从基础概念到高级应用,一步步揭示后端开发的全貌。我们将通过代码示例,让你更好地理解和掌握后端开发的核心技能。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供有价值的信息和启示。
|
26天前
|
存储 缓存 监控
后端开发中的缓存机制:深度解析与最佳实践####
本文深入探讨了后端开发中不可或缺的一环——缓存机制,旨在为读者提供一份详尽的指南,涵盖缓存的基本原理、常见类型(如内存缓存、磁盘缓存、分布式缓存等)、主流技术选型(Redis、Memcached、Ehcache等),以及在实际项目中如何根据业务需求设计并实施高效的缓存策略。不同于常规摘要的概述性质,本摘要直接点明文章将围绕“深度解析”与“最佳实践”两大核心展开,既适合初学者构建基础认知框架,也为有经验的开发者提供优化建议与实战技巧。 ####