1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 | #include <errno.h>
|
21 |
|
22 | static const PropertyAttribute attribute_ro_dd = (PropertyAttribute)(ReadOnly | DontDelete);
|
23 | static const PropertyAttribute attribute_ro_de_dd = (PropertyAttribute)(ReadOnly | DontEnum | DontDelete);
|
24 |
|
25 |
|
26 | #define JSObjFn(obj, name, fnname) \
|
27 | Nan::DefineOwnProperty(obj, Nan::New<String>(name).ToLocalChecked(), Nan::New<FunctionTemplate>(fnname)->GetFunction(), (PropertyAttribute)(DontDelete));
|
28 |
|
29 | static void ReportException(Nan::TryCatch* try_catch) {
|
30 | Nan::HandleScope scope;
|
31 |
|
32 | String::Utf8Value exception(try_catch->Exception());
|
33 | Local<Message> message = try_catch->Message();
|
34 |
|
35 | if (message.IsEmpty()) {
|
36 | printf("%s\n", *exception);
|
37 |
|
38 | } else {
|
39 |
|
40 | String::Utf8Value filename(message->GetScriptResourceName());
|
41 | int linenum = message->GetLineNumber();
|
42 | printf("%s:%i: %s\n", *filename, linenum, *exception);
|
43 |
|
44 | String::Utf8Value sourceline(message->GetSourceLine());
|
45 | char *tmpbuf = *sourceline;
|
46 | for (int i=0, n=sourceline.length(); i<n; ++i) {
|
47 | if (tmpbuf[i] == '\t') {
|
48 | putchar(' ');
|
49 | } else {
|
50 | putchar(tmpbuf[i]);
|
51 | }
|
52 | }
|
53 | putchar('\n');
|
54 |
|
55 |
|
56 | int start = message->GetStartColumn();
|
57 | for (int i = 0; i < start; i++) {
|
58 | putchar(' ');
|
59 | }
|
60 | int end = Nan::GetEndColumn(message).FromJust();
|
61 | for (int i = start; i < end; i++) {
|
62 | putchar('^');
|
63 | }
|
64 | putchar('\n');
|
65 |
|
66 | String::Utf8Value stack_trace(try_catch->StackTrace().ToLocalChecked());
|
67 | if (stack_trace.length() > 0) {
|
68 | printf("%s\n", *stack_trace);
|
69 | }
|
70 | }
|
71 | }
|
72 |
|
73 |
|
74 | NAN_METHOD(readFileSync_) {
|
75 | Nan::HandleScope scope;
|
76 |
|
77 | FILE *f = fopen(*String::Utf8Value(Local<String>::Cast(info[0])), "rb");
|
78 | if (f == NULL) {
|
79 | char str[256];
|
80 | sprintf(str, "Error: readfile open failed. %d %s\n", errno, strerror(errno));
|
81 | return Nan::ThrowError(Nan::New<String>(str).ToLocalChecked());
|
82 | }
|
83 | fseek(f, 0, SEEK_END);
|
84 | size_t s = ftell(f);
|
85 | rewind(f);
|
86 |
|
87 | char *buf = (char*)malloc((s+1)*sizeof(char));
|
88 | size_t r = fread(buf, sizeof(char), s, f);
|
89 | if (r < s) {
|
90 | char str[256];
|
91 | sprintf(str, "Error: readfile read failed. %d %s\n", ferror(f), strerror(ferror(f)));
|
92 | delete[] buf;
|
93 | fclose(f);
|
94 | Nan::ThrowError(str);
|
95 | }
|
96 | buf[s] = 0;
|
97 | Local<String> str = Nan::New<String>(buf).ToLocalChecked();
|
98 | free(buf);
|
99 | fclose(f);
|
100 |
|
101 | info.GetReturnValue().Set(str);
|
102 | }
|
103 |
|
104 |
|
105 |
|
106 |
|
107 | static inline void console_common_1(const Local<Value> &v, FILE* fd, const int deep) {
|
108 | char indent[36] = {};
|
109 | int i, n;
|
110 | int mark = 0;
|
111 | for (i=0; i<deep; ++i) {
|
112 | indent[mark++] = 0x20;
|
113 | indent[mark++] = 0x20;
|
114 | }
|
115 |
|
116 | Local<Value> lv;
|
117 | if (v->IsFunction()) {
|
118 | fprintf(fd, "%s[Function]\n", indent);
|
119 | } else if (v->IsObject()) {
|
120 | Local<Object> obj = Local<Object>::Cast(v);
|
121 | Local<Array> ar = obj->GetPropertyNames();
|
122 | fprintf(fd, "%s{Object}\n", indent);
|
123 | for (i=0, n=ar->Length(); i<n; ++i) {
|
124 | lv = obj->Get(ar->Get(i));
|
125 | fprintf(fd, "%s%s: ", indent, *(String::Utf8Value(Local<String>::Cast(ar->Get(i)))));
|
126 | if (lv->IsFunction()) {
|
127 | fprintf(fd, "%s[Function]\n", indent);
|
128 | } else if (lv->IsObject() || lv->IsArray()) {
|
129 |
|
130 | console_common_1(lv, fd, deep+1);
|
131 | } else {
|
132 | fprintf(fd, "%s%s\n", indent, *(String::Utf8Value(Local<String>::Cast(lv))));
|
133 | }
|
134 | }
|
135 | fprintf(fd, "%s{/Object}\n", indent);
|
136 |
|
137 | } else if (v->IsArray()) {
|
138 | Local<Array> obj = Local<Array>::Cast(v);
|
139 | fprintf(fd, "%s[Array]\n", indent);
|
140 | for (i=0, n=obj->Length(); i<n; ++i) {
|
141 | lv = obj->Get(i);
|
142 | fprintf(fd, "%s%d: ", indent, i);
|
143 | if (lv->IsFunction()) {
|
144 | fprintf(fd, "%s[Function]\n", indent);
|
145 | } else if (lv->IsObject() || lv->IsArray()) {
|
146 | fprintf(fd, "\n");
|
147 | console_common_1(lv, fd, deep+1);
|
148 | } else {
|
149 | fprintf(fd, "%s%s\n", indent, *(String::Utf8Value(Local<String>::Cast(lv))));
|
150 | }
|
151 | }
|
152 | fprintf(fd, "%s[/Array]\n", indent);
|
153 | } else {
|
154 | fprintf(fd, "%s%s\n", indent, *(String::Utf8Value(Local<String>::Cast(v))));
|
155 | }
|
156 | }
|
157 |
|
158 | NAN_METHOD(console_log) {
|
159 | Nan::HandleScope scope;
|
160 |
|
161 | Nan::TryCatch trycatch;
|
162 |
|
163 | for (int i=0, n=info.Length(); i<n; ++i) {
|
164 | console_common_1(info[i], stdout, 0);
|
165 | }
|
166 |
|
167 | if (trycatch.HasCaught()) {
|
168 | ReportException(&trycatch);
|
169 | }
|
170 |
|
171 | info.GetReturnValue().SetUndefined();
|
172 | }
|
173 |
|
174 | NAN_METHOD(console_error) {
|
175 | Nan::HandleScope scope;
|
176 |
|
177 | Nan::TryCatch trycatch;
|
178 |
|
179 | for (int i=0, n=info.Length(); i<n; ++i) {
|
180 | console_common_1(info[i], stderr, 0);
|
181 | }
|
182 |
|
183 | if (trycatch.HasCaught()) {
|
184 | ReportException(&trycatch);
|
185 | }
|
186 |
|
187 | info.GetReturnValue().SetUndefined();
|
188 | }
|