Веб-компоненты в интерпретаторе схемы в JavaScript?Javascript

Форум по Javascript
Ответить
Anonymous
 Веб-компоненты в интерпретаторе схемы в JavaScript?

Сообщение Anonymous »

У меня есть интерпретатор схемы, написанный на JavaScript, который называется LIPS, и макрос define-class, который использует систему прототипов ES5. Но у меня проблема с созданием super().
Я пытаюсь создать PoC super внутри класса. Итак, я могу создавать веб-компоненты:
Это мой код:

Код: Выделить всё


;; MODIFICATION OF define-class MACRO FROM STANDARD LIBRARY
(define (%class-constructor expr parent)
"(%class-constructor expr)

Version of %class-lambda that is used as constructor."
(let ((args (gensym 'args))
(ret (gensym 'ret)))
`(lambda ,args
(let ((,ret (apply ,(cadr expr) (unbind this) ,args)))
(if (and (object? ,parent) (instanceof ,parent ,ret))
,ret
;; we return this to solve issue when constructor
;; return a promise
;; ref: https://stackoverflow.com/a/50885340/387194
this)))))

(define-macro (define-class name parent . body)
"(define-class name parent . body)

Defines a class - JavaScript function constructor with prototype.
parent needs to be class, constructor function, or #null

usage:

(define-class Person Object
(constructor (lambda (self name)
(set-obj! self '_name name)))
(hi (lambda (self)
(display (string-append self._name \" says hi\"))
(newline))))
(define jack (new Person \"Jack\"))
(jack.hi) ; prints \"Jack says hi\""
(let ((g:parent (gensym)))
(let iter ((functions '()) (constructor '()) (lst body))
(if (null? lst)
`(begin
(define ,name ,(if (null? constructor)
`(lambda ())
(%class-constructor constructor parent)))
(set-obj! ,name (Symbol.for "__class__") true)
(let ((,g:parent ,parent ))
(if (not (null? ,g:parent))
(begin
(set-obj! ,name 'prototype (Object.create (. ,g:parent 'prototype)))
(set-obj! (. ,name 'prototype) 'constructor ,name))))
(set-obj! ,name '__name__ ',name)
,@(map (lambda (fn)
`(set-obj! (. ,name 'prototype)
,(%class-method-name (car fn))
,(%class-lambda fn)))
functions))
(let ((item (car lst)))
(if (eq? (car item) 'constructor)
(iter functions item (cdr lst))
(iter (cons item functions) constructor (cdr lst))))))))

;; MAIN CODE
(define-class CurrentDate HTMLElement
(constructor (lambda (self)
(Reflect.construct HTMLElement #() CurrentDate)))
(connectedCallback (lambda (self)
(let ((now (new Date)))
(set! self.textContent (now.toLocaleDateString))))))

(customElements.define "current-date" CurrentDate)



Код Scheme просто использует прототипы ES5 для создания класса. Это всего лишь сопоставление кода JavaScript в схеме 1-1.
Я постоянно получаю сообщение об ошибке:

Uncaught TypeError: Не удалось создать «HTMLElement»: недопустимый конструктор

(Фрагмент стека не показывает правильную ошибку; вам нужно открыть DevTools)
Я тестировал код из: Как в ES5 пишутся классы веб-компонентов?
Код выдает это выражение:

Код: Выделить всё

(apply ,(cadr expr) this ,args)
И (cadr expr):

Код: Выделить всё

(lambda (self) (Reflect.construct HTMLElement #() CurrentDate))
Лямбда-макрос выполняет часть кода, но Reflect.construct не обязательно должен быть первым выражением, как в случае с super. И единственное, что нужно сделать пользовательскому компоненту, — это вернуть узел DOM из вызова конструктора HTMLElement.
Это выполняется без ошибок:

Код: Выделить всё

function HelloElement() {
console.log('x');
const ret = make();
console.log(ret);
console.log(ret instanceof HTMLElement);
return ret;
}
function make() {
return Reflect.construct(HTMLElement, [], HelloElement);
}

customElements.define('hello-element', HelloElement);


Я также пытался вызвать JavaScript из Scheme, но получил ту же ошибку:

Код: Выделить всё

(define js-eval self.eval)
(define-macro (super class)
`((js-eval "(unbind, constructor) => Reflect.construct(HTMLElement, [], unbind(constructor));")
,unbind ,class))

(define-class CurrentDate HTMLElement
(constructor (lambda (self)
(super CurrentDate))))
В LIPS функции имеют то, что я называю мягкой привязкой ( context), который вы можете отменить (получить исходную функцию).
Мне удалось вызвать ту же ошибку в JavaScript, добавив:

Код: Выделить всё

return Promise.resolve(ret);
LIPS иногда может возвращать асинхронный код, от которого я хотел избавиться, но после быстрого теста класс define не возвращает обещание.
Я могу вызвать ту же ошибку, когда вызываю (new CurrentDate) в Scheme и new HelloElement() в примере с JavaScript. Но я не вызываю new в своей схеме? Код запускается с помощью HTML-кода.
Какие еще могут быть проблемы с моим кодом? И возможная основная причина ошибки?

Подробнее здесь: https://stackoverflow.com/questions/798 ... javascript
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»