Coverage Report

Created: 2026-04-12 06:35

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