Coverage Report

Created: 2026-07-16 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsmc.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 "xsAll.h"
39
#include <stdio.h>
40
41
31.9k
#define fxPop() (*(the->stack++))
42
350k
#define fxPush(_SLOT) (*(--the->stack) = (_SLOT))
43
44
void _xsNewArray(txMachine *the, txSlot *res, txInteger length)
45
0
{
46
0
  fxNewArray(the, length);
47
0
  *res = fxPop();
48
0
}
49
50
void _xsNewObject(txMachine *the, txSlot *res)
51
0
{
52
0
  fxNewObject(the);
53
0
  *res = fxPop();
54
0
}
55
56
void _xsNewHostInstance(txMachine *the, txSlot *res, txSlot *proto)
57
0
{
58
0
  mxOverflow(-1);
59
0
  fxPush(*proto);
60
0
  fxNewHostInstance(the);
61
0
  *res = fxPop();
62
0
}
63
64
txBoolean _xsIsInstanceOf(txMachine *the, txSlot *v, txSlot *proto)
65
0
{
66
0
  mxOverflow(-2);
67
0
  fxPush(*proto);
68
0
  fxPush(*v);
69
0
  return fxIsInstanceOf(the);
70
0
}
71
72
txBoolean _xsHas(txMachine *the, txSlot *self, txID id)
73
0
{
74
0
  mxOverflow(-1);
75
0
  fxPush(*self);
76
0
  return mxHasID(id);
77
0
}
78
79
txBoolean _xsHasIndex(txMachine *the, txSlot *self, txIndex index)
80
0
{
81
0
  mxOverflow(-1);
82
0
  fxPush(*self);
83
0
  return fxHasIndex(the, index);
84
0
}
85
86
txBoolean _xsGet(txMachine *the, txSlot *res, txSlot *self, txID id)
87
31.9k
{
88
31.9k
  txBoolean result;
89
31.9k
  mxOverflow(-1);
90
31.9k
  fxPush(*self);
91
31.9k
  result = mxGetID(id);
92
31.9k
  *res = fxPop();
93
31.9k
  return result;
94
31.9k
}
95
96
txBoolean _xsGetAt(txMachine *the, txSlot *res, txSlot *self, txSlot *at)
97
0
{
98
0
  txBoolean result;
99
0
  mxOverflow(-2);
100
0
  fxPush(*self);
101
0
  fxPush(*at);
102
0
  result = fxGetAt(the);
103
0
  *res = fxPop();
104
0
  return result;
105
0
}
106
107
txBoolean _xsGetIndex(txMachine *the, txSlot *res, txSlot *self, txIndex index)
108
0
{
109
0
  txBoolean result;
110
0
  mxOverflow(-1);
111
0
  fxPush(*self);
112
0
  result = mxGetIndex(index);
113
0
  *res = fxPop();
114
0
  return result;
115
0
}
116
117
void _xsSet(txMachine *the, txSlot *self, txID id, txSlot *v)
118
0
{
119
0
  mxOverflow(-2);
120
0
  fxPush(*v);
121
0
  fxPush(*self);
122
0
  mxSetID(id);
123
0
  mxPop();
124
0
}
125
126
void _xsSetAt(txMachine *the, txSlot *self, txSlot *at , txSlot *v)
127
0
{
128
0
  mxOverflow(-3);
129
0
  fxPush(*v);
130
0
  fxPush(*self);
131
0
  fxPush(*at);
132
0
  fxSetAt(the);
133
0
  mxPop();
134
0
}
135
136
void _xsSetIndex(txMachine *the, txSlot *self, txIndex index, txSlot *v)
137
0
{
138
0
  mxOverflow(-2);
139
0
  fxPush(*v);
140
0
  fxPush(*self);
141
0
  mxSetIndex(index);
142
0
  mxPop();
143
0
}
144
145
void _xsDefine(txMachine *the, txSlot *self, txID id, txSlot *v, txFlag attributes)
146
159k
{
147
159k
  mxOverflow(-2);
148
159k
  fxPush(*v);
149
159k
  fxPush(*self);
150
159k
  fxDefineID(the, id, attributes, attributes | XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
151
159k
  mxPop();
152
159k
}
153
154
void _xsDelete(txMachine *the, txSlot *self, txID id)
155
0
{
156
0
  mxOverflow(-1);
157
0
  fxPush(*self);
158
0
  mxDeleteID(id);
159
0
  mxPop();
160
0
}
161
162
void _xsDeleteAt(txMachine *the, txSlot *self, txSlot *at)
163
0
{
164
0
  mxOverflow(-2);
165
0
  fxPush(*self);
166
0
  fxPush(*at);
167
0
  fxDeleteAt(the);
168
0
  mxPop();
169
0
}
170
171
void _xsCall(txMachine *the, txSlot *res, txSlot *self, txUnsigned id, ...)
172
0
{
173
0
  va_list ap;
174
0
  int n;
175
0
  txSlot *v;
176
177
0
  va_start(ap, id);
178
0
  for (n = 0; va_arg(ap, txSlot *) != NULL; n++)
179
0
    ;
180
0
  va_end(ap);
181
0
  mxOverflow(-(n+6));
182
0
  fxPush(*self);
183
0
  fxCallID(the, (txID)id);
184
0
  va_start(ap, id);
185
0
  while ((v = va_arg(ap, txSlot *)) != NULL)
186
0
    fxPush(*v);
187
0
  va_end(ap);
188
0
  fxRunCount(the, n);
189
0
  if (res != NULL)
190
0
    *res = fxPop();
191
0
  else
192
0
    mxPop();
193
0
}
194
195
void _xsNew(txMachine *the, txSlot *res, txSlot *self, txUnsigned id, ...)
196
0
{
197
0
  va_list ap;
198
0
  int n;
199
0
  txSlot *v;
200
201
0
  va_start(ap, id);
202
0
  for (n = 0; va_arg(ap, txSlot *) != NULL; n++)
203
0
    ;
204
0
  va_end(ap);
205
0
  mxOverflow(-(n+6));
206
0
  fxPush(*self);
207
0
  fxNewID(the, (txID)id);
208
0
  va_start(ap, id);
209
0
  while ((v = va_arg(ap, txSlot *)) != NULL)
210
0
    fxPush(*v);
211
0
  va_end(ap);
212
0
  fxRunCount(the, n);
213
0
  *res = fxPop();
214
0
}
215
216
txBoolean _xsTest(txMachine *the, txSlot *v)
217
0
{
218
0
  mxOverflow(-1);
219
0
  fxPush(*v);
220
0
  return fxRunTest(the);
221
0
}
222
223
txInteger fxIncrementalVars(txMachine* the, txInteger theCount)
224
31.9k
{
225
31.9k
  txSlot* aStack = the->scope;
226
31.9k
  txInteger aVar;
227
228
31.9k
  if (aStack - aStack->value.integer != the->stack)
229
0
    mxSyntaxError("C: xsVars: too late");
230
231
31.9k
  mxOverflow(theCount);
232
31.9k
  aVar = aStack->value.integer;
233
31.9k
  aStack->value.integer += theCount;
234
31.9k
  if (theCount > 0) {
235
127k
    while (theCount) {
236
95.7k
      mxPushUndefined();
237
95.7k
      theCount--;
238
95.7k
    }
239
31.9k
  }
240
0
  else
241
0
    the->stack -= theCount;
242
31.9k
  return aVar;
243
31.9k
}
244
245
txInteger _xsArgc(txMachine *the)
246
63.8k
{
247
63.8k
  return mxArgc;
248
63.8k
}
249
250
#ifndef __XSMC_H__
251
enum {
252
  xsBufferNonrelocatable,
253
  xsBufferRelocatable
254
};
255
#endif
256
257
static txInteger _xsmcGetViewBuffer(txMachine *the, txSlot* view, txSlot* buffer, void **data, txUnsigned *count, txBoolean writable)
258
0
{
259
0
  txInteger offset = view->value.dataView.offset;
260
0
  txInteger size = view->value.dataView.size;
261
0
  txSlot* arrayBuffer = buffer->value.reference->next;
262
0
  txSlot* bufferInfo = arrayBuffer->next;
263
0
  if (arrayBuffer->value.arrayBuffer.address == C_NULL)
264
0
    mxTypeError("detached buffer");
265
0
  if (writable && (arrayBuffer->flag & XS_DONT_SET_FLAG))
266
0
    mxTypeError("read-only buffer");
267
0
  if (bufferInfo->value.bufferInfo.maxLength >= 0) {
268
0
    txInteger byteLength = bufferInfo->value.bufferInfo.length;
269
0
    if (offset > byteLength)
270
0
      mxTypeError("out of bounds view");
271
0
    if (size < 0)
272
0
      size = byteLength - offset;
273
0
    else if (offset + size > byteLength)
274
0
      mxTypeError("out of bounds view");
275
0
  }
276
0
  *data = arrayBuffer->value.arrayBuffer.address + offset;
277
0
  *count = size;
278
279
0
  return (XS_ARRAY_BUFFER_KIND == arrayBuffer->kind) ? xsBufferRelocatable : xsBufferNonrelocatable;
280
0
}
281
282
txInteger _xsmcGetBuffer(txMachine *the, txSlot *slot, void **data, txUnsigned *count, txBoolean writable)
283
63.8k
{
284
63.8k
  txSlot* instance;
285
286
63.8k
  if (slot->kind != XS_REFERENCE_KIND)
287
0
    goto bail;
288
289
63.8k
  instance = slot->value.reference;
290
63.8k
  if (!(((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG)))
291
0
    goto bail;
292
293
63.8k
  if (slot->kind == XS_ARRAY_BUFFER_KIND) {
294
63.8k
    txSlot* bufferInfo = slot->next;
295
63.8k
    if (slot->value.arrayBuffer.address == C_NULL)
296
0
      mxTypeError("detached buffer");
297
63.8k
    if (writable && (slot->flag & XS_DONT_SET_FLAG))
298
0
      mxTypeError("read-only buffer");
299
63.8k
    *data = slot->value.arrayBuffer.address;
300
63.8k
    *count = bufferInfo->value.bufferInfo.length;
301
63.8k
    return xsBufferRelocatable;
302
63.8k
  }
303
304
0
  if (slot->kind == XS_TYPED_ARRAY_KIND) {
305
0
    txSlot* view = slot->next;
306
0
    txSlot* buffer = view->next;
307
0
    if (1 != slot->value.typedArray.dispatch->size)
308
0
      goto bail;
309
0
    return _xsmcGetViewBuffer(the, view, buffer, data, count, writable);
310
0
  }
311
  
312
0
  if (slot->kind == XS_HOST_KIND) {
313
0
    txSlot* bufferInfo = slot->next;
314
0
    if (slot->flag & XS_HOST_CHUNK_FLAG)
315
0
      goto bail;
316
0
    if (writable && (slot->flag & XS_DONT_SET_FLAG))
317
0
      mxTypeError("read-only buffer");
318
0
    if (bufferInfo && (bufferInfo->kind == XS_BUFFER_INFO_KIND)) {
319
0
      *data = (uint8_t *)slot->value.host.data;
320
0
      *count = bufferInfo->value.bufferInfo.length;
321
0
    }
322
0
    else
323
0
      mxTypeError("not host buffer");    // Use xsmcSetHostBuffer instead of xsmcSetHostData
324
0
    return xsBufferNonrelocatable;
325
0
  }
326
327
0
  if (slot->kind == XS_DATA_VIEW_KIND) {
328
0
    txSlot* view = slot;
329
0
    txSlot* buffer = view->next;
330
0
    return _xsmcGetViewBuffer(the, view, buffer, data, count, writable);
331
0
  }
332
333
0
bail:
334
0
  mxTypeError("invalid buffer");
335
0
  return xsBufferNonrelocatable;
336
0
}