Coverage Report

Created: 2026-06-28 06:33

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