Coverage Report

Created: 2025-08-28 06:23

/src/moddable/xs/sources/xsScript.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2016-2025  Moddable Tech, Inc.
3
 *
4
 *   This file is part of the Moddable SDK Runtime.
5
 * 
6
 *   The Moddable SDK Runtime is free software: you can redistribute it and/or modify
7
 *   it under the terms of the GNU Lesser General Public License as published by
8
 *   the Free Software Foundation, either version 3 of the License, or
9
 *   (at your option) any later version.
10
 * 
11
 *   The Moddable SDK Runtime is distributed in the hope that it will be useful,
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *   GNU Lesser General Public License for more details.
15
 * 
16
 *   You should have received a copy of the GNU Lesser General Public License
17
 *   along with the Moddable SDK Runtime.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 * This file incorporates work covered by the following copyright and  
20
 * permission notice:  
21
 *
22
 *       Copyright (C) 2010-2016 Marvell International Ltd.
23
 *       Copyright (C) 2002-2010 Kinoma, Inc.
24
 *
25
 *       Licensed under the Apache License, Version 2.0 (the "License");
26
 *       you may not use this file except in compliance with the License.
27
 *       You may obtain a copy of the License at
28
 *
29
 *        http://www.apache.org/licenses/LICENSE-2.0
30
 *
31
 *       Unless required by applicable law or agreed to in writing, software
32
 *       distributed under the License is distributed on an "AS IS" BASIS,
33
 *       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
 *       See the License for the specific language governing permissions and
35
 *       limitations under the License.
36
 */
37
38
#include "xsScript.h"
39
extern void fxAbort(void* console, int status);
40
41
#if defined(__clang__) || defined (__GNUC__)
42
  __attribute__((no_sanitize_address))
43
#endif
44
void fxCheckParserStack(txParser* parser, txInteger line)
45
16.1M
{
46
16.1M
    char x;
47
16.1M
    char *stack = &x;
48
16.1M
    if (stack <= parser->stackLimit) {
49
3
      fxAbort(parser->console, XS_NATIVE_STACK_OVERFLOW_EXIT);
50
3
    }
51
16.1M
}
52
53
txString fxCombinePath(txParser* parser, txString base, txString name)
54
0
{
55
0
  txSize baseLength, nameLength;
56
0
  txString path;
57
0
  txString separator ;
58
#if mxWindows
59
  separator = name;
60
  while (*separator) {
61
    if (*separator == '/')
62
      *separator = '\\';
63
    separator++;
64
  }
65
  separator = strrchr(base, '\\');
66
#else
67
0
  separator = strrchr(base, '/');
68
0
#endif
69
0
  if (separator) {
70
0
    separator++;
71
0
    baseLength = mxPtrDiff(separator - base);
72
0
  }
73
0
  else
74
0
    baseLength = 0;
75
0
  nameLength = mxStringLength(name);
76
0
  path = fxNewParserChunk(parser, baseLength + nameLength + 1);
77
0
  if (baseLength)
78
0
    c_memcpy(path, base, baseLength);
79
0
  c_memcpy(path + baseLength, name, nameLength + 1);
80
0
  return path;
81
0
}
82
83
void fxDisposeParserChunks(txParser* parser)
84
292k
{
85
292k
  txParserChunk** address = &parser->first;
86
292k
  txParserChunk* block;
87
45.1M
  while ((block = *address)) {
88
44.8M
    *address = block->next;
89
44.8M
    c_free(block);
90
44.8M
  }
91
292k
}
92
93
void fxInitializeParser(txParser* parser, void* console, txSize bufferSize, txSize symbolModulo)
94
292k
{
95
292k
  c_memset(parser, 0, sizeof(txParser));
96
292k
  parser->first = C_NULL;
97
292k
  parser->console = console;
98
292k
  parser->stackLimit = fxCStackLimit();
99
  
100
292k
  parser->symbolModulo = symbolModulo;
101
292k
  parser->symbolTable = fxNewParserChunkClear(parser, parser->symbolModulo * sizeof(txSymbol*));
102
103
292k
  parser->emptyString = fxNewParserString(parser, "", 0);
104
105
292k
  parser->ObjectSymbol = fxNewParserSymbol(parser, "Object");
106
292k
  parser->__dirnameSymbol = fxNewParserSymbol(parser, "__dirname");
107
292k
  parser->__filenameSymbol = fxNewParserSymbol(parser, "__filename");
108
292k
  parser->__jsx__Symbol = fxNewParserSymbol(parser, "__jsx__");
109
292k
  parser->__proto__Symbol = fxNewParserSymbol(parser, "__proto__");
110
292k
  parser->allSymbol = fxNewParserSymbol(parser, "*");
111
292k
  parser->argsSymbol = fxNewParserSymbol(parser, "args");
112
292k
  parser->argumentsSymbol = fxNewParserSymbol(parser, "arguments");
113
292k
  parser->arrowSymbol = fxNewParserSymbol(parser, "=>");
114
292k
  parser->asSymbol = fxNewParserSymbol(parser, "as");
115
292k
  parser->asyncSymbol = fxNewParserSymbol(parser, "async");
116
292k
  parser->awaitSymbol = fxNewParserSymbol(parser, "await");
117
292k
  parser->callerSymbol = fxNewParserSymbol(parser, "caller");
118
292k
  parser->constructorSymbol = fxNewParserSymbol(parser, "constructor");
119
292k
  parser->defaultSymbol = fxNewParserSymbol(parser, "default");
120
292k
  parser->doneSymbol = fxNewParserSymbol(parser, "done");
121
292k
  parser->evalSymbol = fxNewParserSymbol(parser, "eval");
122
292k
  parser->exportsSymbol = fxNewParserSymbol(parser, "exports");
123
292k
  parser->fillSymbol = fxNewParserSymbol(parser, "fill");
124
292k
  parser->freezeSymbol = fxNewParserSymbol(parser, "freeze");
125
292k
  parser->fromSymbol = fxNewParserSymbol(parser, "from");
126
292k
  parser->getSymbol = fxNewParserSymbol(parser, "get");
127
292k
  parser->idSymbol = fxNewParserSymbol(parser, "id");
128
292k
  parser->includeSymbol = fxNewParserSymbol(parser, "include");
129
292k
  parser->InfinitySymbol = fxNewParserSymbol(parser, "Infinity");
130
292k
  parser->jsonSymbol = fxNewParserSymbol(parser, "json");
131
292k
  parser->lengthSymbol = fxNewParserSymbol(parser, "length");
132
292k
  parser->letSymbol = fxNewParserSymbol(parser, "let");
133
292k
  parser->metaSymbol = fxNewParserSymbol(parser, "meta");
134
292k
  parser->moduleSymbol = fxNewParserSymbol(parser, "module");
135
292k
  parser->nameSymbol = fxNewParserSymbol(parser, "name");
136
292k
  parser->NaNSymbol = fxNewParserSymbol(parser, "NaN");
137
292k
  parser->nextSymbol = fxNewParserSymbol(parser, "next");
138
292k
  parser->newTargetSymbol = fxNewParserSymbol(parser, "new.target");
139
292k
  parser->ofSymbol = fxNewParserSymbol(parser, "of");
140
292k
  parser->privateConstructorSymbol = fxNewParserSymbol(parser, "#constructor");
141
292k
  parser->prototypeSymbol = fxNewParserSymbol(parser, "prototype");
142
292k
  parser->RangeErrorSymbol = fxNewParserSymbol(parser, "RangeError");
143
292k
  parser->rawSymbol = fxNewParserSymbol(parser, "raw");
144
292k
  parser->returnSymbol = fxNewParserSymbol(parser, "return");
145
292k
  parser->setSymbol = fxNewParserSymbol(parser, "set");
146
292k
  parser->sliceSymbol = fxNewParserSymbol(parser, "slice");
147
292k
  parser->SyntaxErrorSymbol = fxNewParserSymbol(parser, "SyntaxError");
148
292k
  parser->staticSymbol = fxNewParserSymbol(parser, "static");
149
292k
  parser->StringSymbol = fxNewParserSymbol(parser, "String");
150
292k
  parser->targetSymbol = fxNewParserSymbol(parser, "target");
151
292k
  parser->thisSymbol = fxNewParserSymbol(parser, "this");
152
292k
  parser->throwSymbol = fxNewParserSymbol(parser, "throw");
153
292k
  parser->toStringSymbol = fxNewParserSymbol(parser, "toString");
154
292k
  parser->undefinedSymbol = fxNewParserSymbol(parser, "undefined");
155
292k
  parser->uriSymbol = fxNewParserSymbol(parser, "uri");
156
292k
  parser->usingSymbol = fxNewParserSymbol(parser, "using");
157
292k
  parser->valueSymbol = fxNewParserSymbol(parser, "value");
158
292k
  parser->withSymbol = fxNewParserSymbol(parser, "with");
159
292k
  parser->yieldSymbol = fxNewParserSymbol(parser, "yield");
160
  
161
292k
  parser->errorSymbol = NULL;
162
292k
  parser->reportError = fxVReportError;
163
292k
  parser->reportWarning = fxVReportWarning;
164
165
292k
  parser->buffer = fxNewParserChunk(parser, bufferSize);
166
292k
  parser->bufferSize = bufferSize;
167
292k
}
168
169
void* fxNewParserChunk(txParser* parser, txSize size)
170
53.8M
{
171
53.8M
  txParserChunk* block = c_malloc(sizeof(txParserChunk) + size);
172
53.8M
  if (!block)
173
1
      fxAbort(parser->console, XS_NOT_ENOUGH_MEMORY_EXIT);
174
53.8M
  parser->total += sizeof(txParserChunk) + size;
175
53.8M
  block->next = parser->first;
176
53.8M
  parser->first = block;
177
53.8M
  return block + 1;
178
53.8M
}
179
180
void* fxNewParserChunkClear(txParser* parser, txSize size)
181
27.3M
{
182
27.3M
  void* result = fxNewParserChunk(parser, size);
183
27.3M
    c_memset(result, 0, size);
184
27.3M
  return result;
185
27.3M
}
186
187
txString fxNewParserString(txParser* parser, txString buffer, txSize size)
188
18.5M
{
189
18.5M
  if (parser->buffer) { 
190
2.17M
    txString result = fxNewParserChunk(parser, size + 1);
191
2.17M
    c_memcpy(result, buffer, size);
192
2.17M
    result[size] = 0;
193
2.17M
    return result;
194
2.17M
  }
195
16.4M
  return buffer;
196
18.5M
}
197
198
txSymbol* fxNewParserSymbol(txParser* parser, txString theString)
199
18.4M
{
200
18.4M
  txString aString;
201
18.4M
  txSize aLength;
202
18.4M
  txU4 aSum;
203
18.4M
  txU4 aModulo;
204
18.4M
  txSymbol* aSymbol;
205
  
206
18.4M
  aString = theString;
207
18.4M
  aLength = 0;
208
18.4M
  aSum = 0;
209
121M
  while(*aString != 0) {
210
103M
    aLength++;
211
103M
    aSum = (aSum << 1) + *aString++;
212
103M
  }
213
18.4M
  aSum &= 0x7FFFFFFF;
214
18.4M
  aModulo = aSum % parser->symbolModulo;
215
18.4M
  aSymbol = parser->symbolTable[aModulo];
216
29.7M
  while (aSymbol != C_NULL) {
217
12.1M
    if (aSymbol->sum == aSum)
218
11.9M
      if (c_strcmp(aSymbol->string, theString) == 0)
219
833k
        break;
220
11.3M
    aSymbol = aSymbol->next;
221
11.3M
  }
222
18.4M
  if (aSymbol == C_NULL) {
223
17.6M
    aSymbol = fxNewParserChunk(parser, sizeof(txSymbol));
224
17.6M
    aSymbol->next = parser->symbolTable[aModulo];
225
17.6M
    aSymbol->ID = -1;
226
17.6M
    aSymbol->length = aLength + 1;
227
17.6M
    aSymbol->string = fxNewParserString(parser, theString, aLength);
228
17.6M
    aSymbol->sum = aSum;
229
17.6M
    aSymbol->usage = 0;
230
17.6M
    parser->symbolTable[aModulo] = aSymbol;
231
17.6M
  }
232
18.4M
  return aSymbol;
233
18.4M
}
234
235
void fxReportMemoryError(txParser* parser, txInteger line, txString theFormat, ...)
236
25
{
237
25
  c_va_list arguments;
238
25
  parser->error = C_ENOMEM;
239
25
  parser->errorCount++;
240
25
  c_va_start(arguments, theFormat);
241
25
    (*parser->reportError)(parser->console, parser->path ? parser->path->string : C_NULL, line, theFormat, arguments);
242
25
  c_va_end(arguments);
243
25
  if (parser->console) {
244
25
    parser->errorSymbol = parser->RangeErrorSymbol;
245
25
    if (parser->buffer != theFormat) {
246
25
      c_va_start(arguments, theFormat);
247
25
      c_vsnprintf(parser->buffer, parser->bufferSize, theFormat, arguments);
248
25
      c_va_end(arguments);
249
25
    }
250
25
    parser->errorMessage = fxNewParserString(parser, parser->buffer, mxStringLength(parser->buffer));
251
25
  }
252
25
  c_longjmp(parser->firstJump->jmp_buf, 1);
253
25
}
254
255
void fxReportParserError(txParser* parser, txInteger line, txString theFormat, ...)
256
188k
{
257
188k
  c_va_list arguments;
258
188k
  parser->error = C_EINVAL;
259
188k
  parser->errorCount++;
260
188k
  c_va_start(arguments, theFormat);
261
188k
    (*parser->reportError)(parser->console, parser->path ? parser->path->string : C_NULL, line, theFormat, arguments);
262
188k
  c_va_end(arguments);
263
188k
  if (parser->console) {
264
188k
    parser->errorSymbol = parser->SyntaxErrorSymbol;
265
188k
    if (parser->buffer != theFormat) {
266
188k
      c_va_start(arguments, theFormat);
267
188k
      c_vsnprintf(parser->buffer, parser->bufferSize, theFormat, arguments);
268
188k
      c_va_end(arguments);
269
188k
    }
270
188k
    parser->errorMessage = fxNewParserString(parser, parser->buffer, mxStringLength(parser->buffer));
271
188k
    c_longjmp(parser->firstJump->jmp_buf, 1);
272
188k
  }
273
188k
}
274
275
void fxTerminateParser(txParser* parser)
276
292k
{
277
292k
  fxDisposeParserChunks(parser);
278
292k
}
279
280
281
282
283
284
285
286
287
288
289
290
291