Coverage Report

Created: 2026-01-10 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsScript.c
Line
Count
Source
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
15.0M
{
46
15.0M
    char x;
47
15.0M
    char *stack = &x;
48
15.0M
    if (stack <= parser->stackLimit) {
49
3
      fxAbort(parser->console, XS_NATIVE_STACK_OVERFLOW_EXIT);
50
3
    }
51
15.0M
}
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
266k
{
85
266k
  txParserChunk** address = &parser->first;
86
266k
  txParserChunk* block;
87
40.3M
  while ((block = *address)) {
88
40.0M
    *address = block->next;
89
40.0M
    c_free(block);
90
40.0M
  }
91
266k
}
92
93
void fxInitializeParser(txParser* parser, void* console, txSize bufferSize, txSize symbolModulo)
94
266k
{
95
266k
  c_memset(parser, 0, sizeof(txParser));
96
266k
  parser->first = C_NULL;
97
266k
  parser->console = console;
98
266k
  parser->stackLimit = fxCStackLimit();
99
  
100
266k
  parser->symbolModulo = symbolModulo;
101
266k
  parser->symbolTable = fxNewParserChunkClear(parser, parser->symbolModulo * sizeof(txSymbol*));
102
103
266k
  parser->emptyString = fxNewParserString(parser, "", 0);
104
105
266k
  parser->ObjectSymbol = fxNewParserSymbol(parser, "Object");
106
266k
  parser->__dirnameSymbol = fxNewParserSymbol(parser, "__dirname");
107
266k
  parser->__filenameSymbol = fxNewParserSymbol(parser, "__filename");
108
266k
  parser->__jsx__Symbol = fxNewParserSymbol(parser, "__jsx__");
109
266k
  parser->__proto__Symbol = fxNewParserSymbol(parser, "__proto__");
110
266k
  parser->allSymbol = fxNewParserSymbol(parser, "*");
111
266k
  parser->argsSymbol = fxNewParserSymbol(parser, "args");
112
266k
  parser->argumentsSymbol = fxNewParserSymbol(parser, "arguments");
113
266k
  parser->arrowSymbol = fxNewParserSymbol(parser, "=>");
114
266k
  parser->asSymbol = fxNewParserSymbol(parser, "as");
115
266k
  parser->asyncSymbol = fxNewParserSymbol(parser, "async");
116
266k
  parser->awaitSymbol = fxNewParserSymbol(parser, "await");
117
266k
  parser->callSymbol = fxNewParserSymbol(parser, "call");
118
266k
  parser->callerSymbol = fxNewParserSymbol(parser, "caller");
119
266k
  parser->constructorSymbol = fxNewParserSymbol(parser, "constructor");
120
266k
  parser->defaultSymbol = fxNewParserSymbol(parser, "default");
121
266k
  parser->doneSymbol = fxNewParserSymbol(parser, "done");
122
266k
  parser->evalSymbol = fxNewParserSymbol(parser, "eval");
123
266k
  parser->exportsSymbol = fxNewParserSymbol(parser, "exports");
124
266k
  parser->fillSymbol = fxNewParserSymbol(parser, "fill");
125
266k
  parser->freezeSymbol = fxNewParserSymbol(parser, "freeze");
126
266k
  parser->fromSymbol = fxNewParserSymbol(parser, "from");
127
266k
  parser->getSymbol = fxNewParserSymbol(parser, "get");
128
266k
  parser->idSymbol = fxNewParserSymbol(parser, "id");
129
266k
  parser->includeSymbol = fxNewParserSymbol(parser, "include");
130
266k
  parser->InfinitySymbol = fxNewParserSymbol(parser, "Infinity");
131
266k
  parser->jsonSymbol = fxNewParserSymbol(parser, "json");
132
266k
  parser->lengthSymbol = fxNewParserSymbol(parser, "length");
133
266k
  parser->letSymbol = fxNewParserSymbol(parser, "let");
134
266k
  parser->metaSymbol = fxNewParserSymbol(parser, "meta");
135
266k
  parser->moduleSymbol = fxNewParserSymbol(parser, "module");
136
266k
  parser->nameSymbol = fxNewParserSymbol(parser, "name");
137
266k
  parser->NaNSymbol = fxNewParserSymbol(parser, "NaN");
138
266k
  parser->NativeSymbol = fxNewParserSymbol(parser, "Native");
139
266k
  parser->nativeSymbol = fxNewParserSymbol(parser, "native");
140
266k
  parser->nextSymbol = fxNewParserSymbol(parser, "next");
141
266k
  parser->newTargetSymbol = fxNewParserSymbol(parser, "new.target");
142
266k
  parser->ofSymbol = fxNewParserSymbol(parser, "of");
143
266k
  parser->privateConstructorSymbol = fxNewParserSymbol(parser, "#constructor");
144
266k
  parser->prototypeSymbol = fxNewParserSymbol(parser, "prototype");
145
266k
  parser->RangeErrorSymbol = fxNewParserSymbol(parser, "RangeError");
146
266k
  parser->rawSymbol = fxNewParserSymbol(parser, "raw");
147
266k
  parser->returnSymbol = fxNewParserSymbol(parser, "return");
148
266k
  parser->setSymbol = fxNewParserSymbol(parser, "set");
149
266k
  parser->sliceSymbol = fxNewParserSymbol(parser, "slice");
150
266k
  parser->SyntaxErrorSymbol = fxNewParserSymbol(parser, "SyntaxError");
151
266k
  parser->staticSymbol = fxNewParserSymbol(parser, "static");
152
266k
  parser->StringSymbol = fxNewParserSymbol(parser, "String");
153
266k
  parser->targetSymbol = fxNewParserSymbol(parser, "target");
154
266k
  parser->thisSymbol = fxNewParserSymbol(parser, "this");
155
266k
  parser->throwSymbol = fxNewParserSymbol(parser, "throw");
156
266k
  parser->toStringSymbol = fxNewParserSymbol(parser, "toString");
157
266k
  parser->undefinedSymbol = fxNewParserSymbol(parser, "undefined");
158
266k
  parser->uriSymbol = fxNewParserSymbol(parser, "uri");
159
266k
  parser->usingSymbol = fxNewParserSymbol(parser, "using");
160
266k
  parser->valueSymbol = fxNewParserSymbol(parser, "value");
161
266k
  parser->withSymbol = fxNewParserSymbol(parser, "with");
162
266k
  parser->yieldSymbol = fxNewParserSymbol(parser, "yield");
163
  
164
266k
  parser->errorSymbol = NULL;
165
266k
  parser->reportError = fxVReportError;
166
266k
  parser->reportWarning = fxVReportWarning;
167
168
266k
  parser->buffer = fxNewParserChunk(parser, bufferSize);
169
266k
  parser->bufferSize = bufferSize;
170
266k
}
171
172
void* fxNewParserChunk(txParser* parser, txSize size)
173
49.0M
{
174
49.0M
  txParserChunk* block = c_malloc(sizeof(txParserChunk) + size);
175
49.0M
  if (!block)
176
1
      fxAbort(parser->console, XS_NOT_ENOUGH_MEMORY_EXIT);
177
49.0M
  parser->total += sizeof(txParserChunk) + size;
178
49.0M
  block->next = parser->first;
179
49.0M
  parser->first = block;
180
49.0M
  return block + 1;
181
49.0M
}
182
183
void* fxNewParserChunkClear(txParser* parser, txSize size)
184
24.1M
{
185
24.1M
  void* result = fxNewParserChunk(parser, size);
186
24.1M
    c_memset(result, 0, size);
187
24.1M
  return result;
188
24.1M
}
189
190
txString fxNewParserString(txParser* parser, txString buffer, txSize size)
191
17.5M
{
192
17.5M
  if (parser->buffer) { 
193
1.79M
    txString result = fxNewParserChunk(parser, size + 1);
194
1.79M
    c_memcpy(result, buffer, size);
195
1.79M
    result[size] = 0;
196
1.79M
    return result;
197
1.79M
  }
198
15.7M
  return buffer;
199
17.5M
}
200
201
txSymbol* fxNewParserSymbol(txParser* parser, txString theString)
202
17.4M
{
203
17.4M
  txString aString;
204
17.4M
  txSize aLength;
205
17.4M
  txU4 aSum;
206
17.4M
  txU4 aModulo;
207
17.4M
  txSymbol* aSymbol;
208
  
209
17.4M
  aString = theString;
210
17.4M
  aLength = 0;
211
17.4M
  aSum = 0;
212
115M
  while(*aString != 0) {
213
98.0M
    aLength++;
214
98.0M
    aSum = (aSum << 1) + *aString++;
215
98.0M
  }
216
17.4M
  aSum &= 0x7FFFFFFF;
217
17.4M
  aModulo = aSum % parser->symbolModulo;
218
17.4M
  aSymbol = parser->symbolTable[aModulo];
219
24.2M
  while (aSymbol != C_NULL) {
220
7.54M
    if (aSymbol->sum == aSum)
221
7.13M
      if (c_strcmp(aSymbol->string, theString) == 0)
222
723k
        break;
223
6.82M
    aSymbol = aSymbol->next;
224
6.82M
  }
225
17.4M
  if (aSymbol == C_NULL) {
226
16.7M
    aSymbol = fxNewParserChunk(parser, sizeof(txSymbol));
227
16.7M
    aSymbol->next = parser->symbolTable[aModulo];
228
16.7M
    aSymbol->ID = -1;
229
16.7M
    aSymbol->length = aLength + 1;
230
16.7M
    aSymbol->string = fxNewParserString(parser, theString, aLength);
231
16.7M
    aSymbol->sum = aSum;
232
16.7M
    aSymbol->usage = 0;
233
16.7M
    parser->symbolTable[aModulo] = aSymbol;
234
16.7M
  }
235
17.4M
  return aSymbol;
236
17.4M
}
237
238
void fxReportMemoryError(txParser* parser, txInteger line, txString theFormat, ...)
239
23
{
240
23
  c_va_list arguments;
241
23
  parser->error = C_ENOMEM;
242
23
  parser->errorCount++;
243
23
  c_va_start(arguments, theFormat);
244
23
    (*parser->reportError)(parser->console, parser->path ? parser->path->string : C_NULL, line, theFormat, arguments);
245
23
  c_va_end(arguments);
246
23
  if (parser->console) {
247
23
    parser->errorSymbol = parser->RangeErrorSymbol;
248
23
    if (parser->buffer != theFormat) {
249
23
      c_va_start(arguments, theFormat);
250
23
      c_vsnprintf(parser->buffer, parser->bufferSize, theFormat, arguments);
251
23
      c_va_end(arguments);
252
23
    }
253
23
    parser->errorMessage = fxNewParserString(parser, parser->buffer, mxStringLength(parser->buffer));
254
23
  }
255
23
  c_longjmp(parser->firstJump->jmp_buf, 1);
256
23
}
257
258
void fxReportParserError(txParser* parser, txInteger line, txString theFormat, ...)
259
143k
{
260
143k
  c_va_list arguments;
261
143k
  parser->error = C_EINVAL;
262
143k
  parser->errorCount++;
263
143k
  c_va_start(arguments, theFormat);
264
143k
    (*parser->reportError)(parser->console, parser->path ? parser->path->string : C_NULL, line, theFormat, arguments);
265
143k
  c_va_end(arguments);
266
143k
  if (parser->console) {
267
143k
    parser->errorSymbol = parser->SyntaxErrorSymbol;
268
143k
    if (parser->buffer != theFormat) {
269
143k
      c_va_start(arguments, theFormat);
270
143k
      c_vsnprintf(parser->buffer, parser->bufferSize, theFormat, arguments);
271
143k
      c_va_end(arguments);
272
143k
    }
273
143k
    parser->errorMessage = fxNewParserString(parser, parser->buffer, mxStringLength(parser->buffer));
274
143k
    c_longjmp(parser->firstJump->jmp_buf, 1);
275
143k
  }
276
143k
}
277
278
void fxTerminateParser(txParser* parser)
279
266k
{
280
266k
  fxDisposeParserChunks(parser);
281
266k
}
282
283
284
285
286
287
288
289
290
291
292
293
294