Coverage Report

Created: 2026-05-16 07:11

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