You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
def JS2C(source, target):
modules = []
consts = {}
macros = {}
macro_lines = []
for s in source:
if (os.path.split(str(s))[1]).endswith('macros.py'):
macro_lines.extend(ReadLines(str(s)))
else:
modules.append(s)
# Process input from all *macro.py files
// 拿到宏定义
(consts, macros) = ReadMacros(macro_lines)
# Build source code lines
definitions = []
initializers = []
for name in modules:
lines = ReadFile(str(name))
// 替换宏定义
lines = ExpandConstants(lines, consts)
lines = ExpandMacros(lines, macros)
deprecated_deps = None
# On Windows, "./foo.bar" in the .gyp file is passed as "foo.bar"
# so don't assume there is always a slash in the file path.
if '/' in name or '\\' in name:
split = re.split('/|\\\\', name)
if split[0] == 'deps':
if split[1] == 'node-inspect' or split[1] == 'v8':
deprecated_deps = split[1:]
split = ['internal'] + split
else:
split = split[1:]
name = '/'.join(split)
# if its a gypi file we're going to want it as json
# later on anyway, so get it out of the way now
if name.endswith(".gypi"):
lines = re.sub(r'#.*?\n', '', lines)
lines = re.sub(r'\'', '"', lines)
name = name.split('.', 1)[0]
var = name.replace('-', '_').replace('/', '_')
key = '%s_key' % var
value = '%s_value' % var
definitions.append(Render(key, name))
definitions.append(Render(value, lines))
initializers.append(INITIALIZER.format(key=key, value=value))
if deprecated_deps is not None:
name = '/'.join(deprecated_deps)
name = name.split('.', 1)[0]
var = name.replace('-', '_').replace('/', '_')
key = '%s_key' % var
value = '%s_value' % var
definitions.append(Render(key, name))
definitions.append(Render(value, DEPRECATED_DEPS.format(module=name)))
initializers.append(INITIALIZER.format(key=key, value=value))
# Emit result
output = open(str(target[0]), "w")
output.write(TEMPLATE.format(definitions=''.join(definitions),
initializers=''.join(initializers)))
output.close()
def Render(var, data):
# Treat non-ASCII as UTF-8 and convert it to UTF-16.
if any(ord(c) > 127 for c in data):
template = TWO_BYTE_STRING
data = map(ord, data.decode('utf-8').encode('utf-16be'))
data = [data[i] * 256 + data[i+1] for i in xrange(0, len(data), 2)]
data = ToCArray(data)
else:
template = ONE_BYTE_STRING
data = ToCString(data)
return template.format(var=var, data=data)
上一篇讲node运行的文章中,我们提到了LoadEnvironment的LoadersBootstrapperSource方法,其从node_javascript.cc中获取loader文件内容的ascII码,node_javascript.cc在out/Debug/gen中,它是如何产生的呢?
本篇文章就是来介绍node_javascript.cc是如何产生的以及其中的内容。
node_js2c
下面是node.gyp定义的node_js2c目标:
inputs
我们可以看到inputs中主要有三个输入,library_files、./config.gypi、tools/check_macros.py。
library_files
其中library_files包含如下文件:
基本上是lib和dep中的一些.js文件。
./config.gypi
./config.gypi主要定义了一些target_defaults(作用域.gyp文件中所有的targets)和一些变量。
tools/check_macros.py
宏定义:
outputs
outputs很简单,在debug模式下就是out/Debug/node_javascript.cc。
action
翻译成指令就是:
js2c.py
下面我们来看下js2c.py里做了什么?
调用了JS2C,并将inputs中的所有文件路径作为参数传进去。
我们来看下JS2C:
这里一共做了如下几件事:
render
判断文件中字符的ascII码是否超过127,超过的字符被转成UTF-16。
node_javascript.cc
node_javascript.cc主要有以下几部分组成:
1.各个模块key、value对应的结构体的定义
我们可以看到数组和两个struct,其中raw_internal_bootstrap_loaders_key和raw_internal_bootstrap_loaders_value分别记录bootstrap_loaders的key和value(文件内容),两个结构体internal_bootstrap_loaders_key和internal_bootstrap_loaders_value均有方法ToStringChecked,而ToStringChecked其实会去找data()方法,也就是说internal_bootstrap_loaders_value.ToStringChecked()便会返回对应的ascII码。
2.初始化函数定义(initializers)
这里主要是将各个模块的key、value挂载在exports对象中,可以在.cpp或者.js中取得文件内容进行执行等操作。
总结
本文主要介绍node_javascript.cc的产生和内容,这其实也是node中获取native模块最关键的地方。到此为止,已经介绍了node中builtin和native模块的由来,大家也可以和上一篇文章的中所提到的getBinding串起来了。
The text was updated successfully, but these errors were encountered: