Quantcast
Channel: Active questions tagged javascript - Stack Overflow
Viewing all articles
Browse latest Browse all 140042

function arbitrarily loses access to closure

$
0
0

Symbol.toPrimitive method, invoked within tagged template literal loses access to the closure.

To reproduce, simply paste the provided code snippet in dev console, run it with and without tag-function. Any relevant articles are highly appreciated.

P.S. I would also appreciate if you give me an idea how and where to debug js code (including node.js). I'm interested in lexical environment, execution context and call stack.

const isEmptyString = /^\s*$/;

class Thread {
  constructor() {
    this.scope = {
      current: '/test|0::0'
    };

    this.context = {
      current: '/test|0'
    };

    this.html = (strings, ...interpolations) => {
      var output = '';
      var prevMode = this._mode;

      this._mode = 'html';

      var {
        length
      } = interpolations;
      output += strings[0]

      for (let i = 0; i < length; ++i) {
        output += String(interpolations[i]) + strings[i + 1];
      }

      this._mode = prevMode;
      return output;
    };
  }


  get id() {
    var fragment;

    const scope = this.scope.current;
    const context = this.context.current;

    return Object.defineProperties(function self(newFragment) {
      fragment = newFragment;
      return self;
    }, {
      scope: {
        get() {
          return scope
        }
      },
      context: {
        get() {
          return context
        }
      },
      fragment: {
        get() {
          return fragment
        }
      },

      [Symbol.toPrimitive]: {
        value: hint => {
          console.log('::', fragment, '::');
          const isFragmentDefined = !isEmptyString.test(fragment);

          const quote = isFragmentDefined ? '\'' : '';
          const suffix = isFragmentDefined ? `::${fragment}` : '';

          if (isFragmentDefined) fragment = '';

          switch (true) {
            case this._mode === 'html':
              return `node=${quote}${scope}${suffix}${quote}`;
            case this._mode === 'css':
              return `${context}${suffix}`.replace(invalidCSS, char => `\\${char}`);

            default:
              return `${scope}${suffix}`;
          }
        }
      }
    });
  }
}

let thread = new Thread();



async function article() {
  let {
    id,
    html
  } = thread;

  let links = html `
    <ul><li ${id('C-first-id')}></li><li ${id('C-second-id')}></li><li ${id('C-third-id')}></li><li ${id('C-fourth-id')}></li></ul>
  `;

  return html `
    <article><h1 ${id('B-first-id')}>Some header</h1><p ${id('B-second-id')}>Lorem ipsum...</p><p ${id('B-third-id')}>Lorem ipsum...</p><p ${id('B-fourth-id')}>Lorem ipsum...</p><section>
        ${links}</section></article>
  `;
}

async function content() {
  let {
    id,
    html
  } = thread;

  return html `
    <main><div><h1 ${id('A-first-id')}>Last article</h1><div><a href='#' ${id('A-second-id')}>More articles like this</a>
          ${await article()}<a href='#' ${id('A-third-id')}>Something else...</a><a href='#' ${id('A-fourth-id')}>Something else...</a></div></div></main>
  `;
}

content();

Viewing all articles
Browse latest Browse all 140042

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>