Coverage Report

Created: 2026-05-16 07:11

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